2017北京师范大学ACM校赛 J Just A String (KMP)
2017-04-26 11:51
381 查看
题目原文:https://acm.bnu.edu.cn/v3/problem_show.php?pid=52516
解题思路:本题很容易陷入的一个思维误区就是一定要枚举前缀和后缀,这样的话复杂度是O(n^3),肯定会超时的。但其实如果对KMP这个算法理解比较深刻的话,可以发现题目中要求的操作,只需要对KMP算法做一点补充就可以完成。每次枚举一个后缀,作为模板串,当他在原串中匹配的时候,每当有元素匹配的时候就可以很容易的得到A
B C的值,而且可以认为包含了所有的情况,不考虑B = 0,因为不影响结果。
心得:当时比赛的时候就没有想到这一点,最开始想用二分+hash做,后来发现这个想法有bug,还是对kmp的理解不够深刻,如果再做出这道题就可以进前6了。
AC代码:
/*
@Author: wchhlbt
@Date: 2017/4/26
*/
#include <bits/stdc++.h>
#define Fori(x) for(int i=0;i<x;i++)
#define Forj(x) for(int j=0;j<x;j++)
#define maxn 50005
#define inf 0x3f3f3f3f
#define ONES(x) __builtin_popcount(x)
using namespace std;
typedef long long ll ;
const double eps =1e-8;
const int mod = 1000000007;
typedef pair<int, int> P;
const double PI = acos(-1.0);
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
ll ans;
int f[maxn];//失配函数
void getFail(string &p)
{
int plen = p.length();
f[0] = 0; f[1] = 0;
for(int i = 1; i<plen; i++){
int j = f[i];
while(j && p[i]!=p[j]) j = f[j];
f[i+1] = (p[i]==p[j]) ? j+1 : 0;
}
}
int find(string &s, string &p)//s->待匹配文本串 p->模板串
{
int slen = s.length();
int plen = p.length();
getFail(p);
int j = 0;
int cnt = 0;
for(int i = 0; i<slen; i++){
while(j && s[i]!=p[j]) j = f[j];
if(s[i]==p[j]){
int len = j+1;//只需要补充这三行
ll A = i+1-len; ll B = len; ll C = plen - len;
ans ^= A*B*B*C;
j++;
}
if(j==plen){
j = f[j];//不考虑重叠时,此处置0
//return i + 1 -plen; 返回第一个匹配的位置
cnt++;
}
}
return cnt;
}
int main()
{
//freopen("test.txt","r",stdin);
ios_base::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
ans = 0;
int len = s.length();
for(int i = 0; i<len; i++){
string tmp = s.substr(i);
getFail(tmp);
find(s,tmp);
}
cout << ans << endl;
}
return 0;
}
解题思路:本题很容易陷入的一个思维误区就是一定要枚举前缀和后缀,这样的话复杂度是O(n^3),肯定会超时的。但其实如果对KMP这个算法理解比较深刻的话,可以发现题目中要求的操作,只需要对KMP算法做一点补充就可以完成。每次枚举一个后缀,作为模板串,当他在原串中匹配的时候,每当有元素匹配的时候就可以很容易的得到A
B C的值,而且可以认为包含了所有的情况,不考虑B = 0,因为不影响结果。
心得:当时比赛的时候就没有想到这一点,最开始想用二分+hash做,后来发现这个想法有bug,还是对kmp的理解不够深刻,如果再做出这道题就可以进前6了。
AC代码:
/*
@Author: wchhlbt
@Date: 2017/4/26
*/
#include <bits/stdc++.h>
#define Fori(x) for(int i=0;i<x;i++)
#define Forj(x) for(int j=0;j<x;j++)
#define maxn 50005
#define inf 0x3f3f3f3f
#define ONES(x) __builtin_popcount(x)
using namespace std;
typedef long long ll ;
const double eps =1e-8;
const int mod = 1000000007;
typedef pair<int, int> P;
const double PI = acos(-1.0);
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
ll ans;
int f[maxn];//失配函数
void getFail(string &p)
{
int plen = p.length();
f[0] = 0; f[1] = 0;
for(int i = 1; i<plen; i++){
int j = f[i];
while(j && p[i]!=p[j]) j = f[j];
f[i+1] = (p[i]==p[j]) ? j+1 : 0;
}
}
int find(string &s, string &p)//s->待匹配文本串 p->模板串
{
int slen = s.length();
int plen = p.length();
getFail(p);
int j = 0;
int cnt = 0;
for(int i = 0; i<slen; i++){
while(j && s[i]!=p[j]) j = f[j];
if(s[i]==p[j]){
int len = j+1;//只需要补充这三行
ll A = i+1-len; ll B = len; ll C = plen - len;
ans ^= A*B*B*C;
j++;
}
if(j==plen){
j = f[j];//不考虑重叠时,此处置0
//return i + 1 -plen; 返回第一个匹配的位置
cnt++;
}
}
return cnt;
}
int main()
{
//freopen("test.txt","r",stdin);
ios_base::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
ans = 0;
int len = s.length();
for(int i = 0; i<len; i++){
string tmp = s.substr(i);
getFail(tmp);
find(s,tmp);
}
cout << ans << endl;
}
return 0;
}
相关文章推荐
- 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string 【KMP+树状数组】
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛-G: Query on a string(线段树+预处理)
- 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string(KMP+树状数组)
- 2017 ACM/ICPC Asia Regional Shenyang Online//string string string(后缀自动机,未学习)
- [计蒜客16956] Query on a string [2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 G]
- 2017西安交大ACM小学期 美妙音乐[差分KMP匹配]
- 2016-2017 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2016) C Castle (kmp)
- HDU-2017 ACM/ICPC Asia Regional Shenyang Online-1001-string string string
- 山东理工大学2017校赛 3930皮卡丘的梦想2—线段树加状压 3926bLue的二叉树-KMP或hash 3914校赛~校赛~-打表找规律
- HDU 6194 String ACM/ICPC 2017 Shenyang Online(后缀数组+容斥原理+线段树/ST)
- 2017 西南交通大学ACM校赛简易题解
- HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 - G Query on a string (KMP+树状数组)
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 Query on a string(字符串+树状数组)
- 计蒜客-2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛-G-Query on a string
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛(G. Query on a string)kmp+线段树
- 计蒜客 16956 Query on a string(2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 G)
- 【2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 G】Query on a string
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 G题 Query on a string
- 2017西安交大ACM小学期 神器插座 KMP匹配