- 题意:
- 扩展kmp的匹配次数。
- 题解:
- 扩展kmp就是:定义母串S和子串T,S的长度为n,T的长度为m;求 字符串T 与 字符串S的每一个后缀 的最长公共前缀;
- 直接用模板写就行了
- 代码:
#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> using namespace std; #define ll long long const int MAX=1000010; //字符串长度最大值 int next1[MAX],extend[MAX]; char a[MAX],b[MAX]; //预处理计算Next数组 void getNext(char str[]) { int i=0,j,po,len=strlen(str); next1[0]=len; //初始化next[0] while(str[i]==str[i+1] && i+1<len) i++; next1[1]=i; //计算next[1] po=1; //初始化po的位置 for(i=2;i<len;i++) { if(next1[i-po]+i < next1[po]+po) //第一种情况,可以直接得到next[i]的值 next1[i]=next1[i-po]; else //第二种情况,要继续匹配才能得到next[i]的值 { j = next1[po]+po-i; if(j<0) j=0; //如果i>po+next[po],则要从头开始匹配 while(i+j<len && str[j]==str[j+i]) j++; next1[i]=j; po=i; //更新po的位置 } } } //计算extend数组 void EXKMP(char s1[],char s2[]) { int i=0,j,po,len=strlen(s1),l2=strlen(s2); getNext(s2); //计算子串的next数组 while(s1[i]==s2[i] && i<l2 && i<len) i++; extend[0]=i; po=0; //初始化po的位置 for(i=1;i<len;i++) { if(next1[i-po]+i < extend[po]+po) //第一种情况,直接可以得到extend[i]的值 extend[i]=next1[i-po]; else //第二种情况,要继续匹配才能得到extend[i]的值 { j = extend[po]+po-i; if(j<0) j=0; //如果i>extend[po]+po则要从头开始匹配 while(i+j<len && j<l2 && s1[j+i]==s2[j]) j++; extend[i]=j; po=i; //更新po的位置 } } } int main() { int t; scanf("%d",&t); while(t--) { memset(extend,0,sizeof(extend)); memset(next1,0,sizeof(next1)); ll sum = 0; scanf("%s",a); int l = strlen(a); strcpy(b,a); b[l] = '\0'; EXKMP(a,b); for(int i=1;i<l;i++) { //cout<<extend[i]+1<<" "; sum += min((extend[i]+1),l-i); } //cout<<endl; cout<<sum<<endl; } }