HDU_3336 Count the string(KMP)
2015-08-19 10:26
357 查看
题目请点我
题解:
题意是在确定了一个前串后,问能找到多少个与前串对应的后串。注意后串是可以重叠的,比如aaaaaa,若固定前串为aa,则后传为aaaa,共有三个与之匹配,所以共有四个aa字串。最开始的思路是枚举字串的长度,但是是O(N^2)的时间复杂度,超时了很多次。后来借鉴同学的方法,换了一种思路,每次利用while循环找到以A[i]结尾的长度不大于i/2的匹配子串。不考虑子串的长度,而是考虑共有多少个符合条件的子串。可以证明所有的子串都是唯一的,很好的方法。
代码实现:
题解:
题意是在确定了一个前串后,问能找到多少个与前串对应的后串。注意后串是可以重叠的,比如aaaaaa,若固定前串为aa,则后传为aaaa,共有三个与之匹配,所以共有四个aa字串。最开始的思路是枚举字串的长度,但是是O(N^2)的时间复杂度,超时了很多次。后来借鉴同学的方法,换了一种思路,每次利用while循环找到以A[i]结尾的长度不大于i/2的匹配子串。不考虑子串的长度,而是考虑共有多少个符合条件的子串。可以证明所有的子串都是唯一的,很好的方法。
代码实现:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #define MAX 200000 using namespace std; int T; int N; int res; int len; char A[MAX]; char B[MAX]; int Next[MAX]; void solve(); void getnext(int x); const int mod = 10007; int main() { scanf("%d",&T); while( T-- ){ scanf("%d",&N); getchar(); gets(A); res = 0; len = strlen(A); getnext(len); solve(); printf("%d\n",res); } return 0; } void solve(){ int j = 0; for( int i = 1; i <= len; i++ ){ j = i; //while 循环向前查找 while( Next[j] > 0 ){ if( Next[j]*2 < i+1 ){ res++; res%=mod; } j = Next[j]; } } res = (res%mod+len%mod)%mod; return ; } void getnext(int x){ memset(Next,0,sizeof(Next)); Next[0] = -1; int i = 0, j = -1; while( i < x ){ if( j == -1 || A[i] == A[j] ){ Next[++i] = ++j; } else{ j = Next[j]; } } }
相关文章推荐