循环节
由Next表可知。
#include <cstdio>
#include <cstring>
#define maxl 1000000
void getNext(char * s, int len, int next[])
{
int t=next[0]=-1;
int j=0;
do ( 0>t || s[j]==s[t] ) ? next[++j] = ++t : t=next[t];
while( j != len-1 );
}
int next[maxl+10];
// s, len: 输入字符串(题目中的c)及长度
// 返回值:题目中 a 串的最短长度
int solve(char *s, int len)
{
getNext(s, len, next);
return len-1 - next[len-1] ;
}
/* =========== 代码实现结束 =========== */
char s[maxl + 10];
int main()
{
int len;
scanf("%d%s", &len, s);
printf("%d\n", solve(s, len));
return 0;
}
注意 AC自动机 与 KMP算法类似。
字符串匹配
不过代码里的next表生成有点迷。我再看看再说
#include <vector>
#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
// ================= 代码实现开始 =================
//Next:KMP 算法中的Next数组
vector<int> Next;
// 这是匹配函数,将所有匹配位置求出并返回
// n:串 A 的长度
// A:题目描述中的串 A
// m:串 B 的长度
// B:题目描述中的串 B
// 返回值:一个 vector<int>,从小到大依次存放各匹配位置
vector<int> match(int n, string A, int m, string B) {
Next.resize(m); //初始化
int j=Next[0] = -1; //j为匹配失败时跳转到的位置
for(int i=1; i<m; ++i){
while( j!=-1 && B[i]!=B[j+1])//如果下一位无法匹配,则利用Next数组跳转
j=Next[j];
if( B[i] == B[j+1] )
++j; //q当前位置匹配,++j
Next[i]=j; //记录当前位的Next数组
if(j==m-1)
j=Next[j];
}
j = -1;
vector<int> ans;
for(int i=0; i<n; ++i){
while(j!=-1 && A[i]!=B[j+1]) //如果下一位无法匹配,则利用Next数组跳转
j=Next[j];
if(A[i]==B[j+1])
++j;//当前位置匹配
if(j == m-1)
ans.push_back(i-m+1);
if(j == m-1)
j=Next[j];
}
return ans;
}
// ================= 代码实现结束 =================
int main() {
ios::sync_with_stdio(false);
int n, m;
string A, B;
cin >> n >> A;
cin >> m >> B;
vector<int> ans = match(n, A, m, B);
for (vector<int>::iterator it = ans.begin(); it != ans.end(); ++it)
cout << *it << '\n';
return 0;
}