您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐