kmp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e6 + 9;
const ll inf = 0x3f3f3f3f;
char a[N];
char b[N];
int ne[N];
void solve() {
scanf("%s", (a + 1));
scanf("%s", (b + 1));
int n = strlen(b + 1);
int m = strlen(a + 1);
for (int i = 2, j = 0; i <= n; i ++) {
while (j && b[i] != b[j + 1])j = ne[j];
ne[i] = (b[j + 1] == b[i]?++j:j);
}
for (int i = 1, j = 0; i <= m; i ++) {
while ( j && b[j + 1] != a[i])j = ne[j];
if (b[j + 1] == a[i])j++;
if (j == n) {
printf("%d\n", i-n + 1 );
}
}
for (int i = 1; i <= n; i ++) printf("%d ", ne[i]);
}
signed main() {
ll t = 1;//cin >> t;
while (t--) solve();
}
ac自动机
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e5 + 9;
const ll inf = 0x3f3f3f3f;
int n;
vector<int>G[N];
string ch[N];
queue<int>q;
int dp[N];
struct AC {
int tr[N][27], idx;
string str;
int ne[N];
void init() {
memset(tr, 0, sizeof tr);
memset(ne, 0, sizeof ne);
memset(dp, 0, sizeof dp);
memset(ch, 0, sizeof ch);
for (int i = 0; i <= n; i ++) {
G[i].clear();
}
idx = 0;
}
void insert() {
int p = 0;
for (int i = 0; str[i]; i ++) {
int t = str[i] - 'a';
if (!tr[p][t])tr[p][t] = ++ idx;
p = tr[p][t];
}
ch[p] = str;
}
void build() {
while (!q.empty())q.pop();
for (int i = 0; i < 26; i ++)
if (tr[0][i])q.push(tr[0][i]);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i ++) {
int p = tr[u][i];
if (p) {//这里是手画理解的
ne[p] = tr[ne[u]][i];
q.push(p);
} else
tr[u][i] = tr[ne[u]][i];
}
}
}
}T;
vector<string> ans;
int ans_cnt;
void solve() {
while (~scanf("%d", &n)) {
if (n == 0)exit(0);
ans_cnt = 0;
T.init();
for (int i = 0; i < n; i ++) {
cin >> T.str;
T.insert();
}
T.build();
for (int i = 1; i <= T.idx; i ++) {
G[i].push_back(T.ne[i]);
G[T.ne[i]].push_back(i);
}
cin >> T.str;
int res = 0;
for (int i = 0, j = 0; T.str[i]; i ++) {
int t = T.str[i] - 'a';
while (j && !T.tr[j][t])j = T.ne[j];
if (T.tr[j][t]) j = T.tr[j][t];
int p = j;
while (p ) {//这里就正常找
dp[p]++;
p = T.ne[p];
}
}
for (int i = 0; i <= T.idx; i ++) {
if (ch[i].size() != 0) {
if (dp[i] > ans_cnt) {
ans_cnt = dp[i];ans.clear();
ans.push_back(ch[i]);
} else if (dp[i] == ans_cnt){
ans.push_back(ch[i]);
}
}
}
cout << ans_cnt <<"\n";
for (auto s:ans)cout << s << "\n";
}
}
signed main() {
ll t = 1;//cin >> t;
//scanf("%d", &t);
while (t--) {
solve();
}
}
后缀数组
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e6 + 9;
const ll inf = 0x3f3f3f3f;
struct Suffix_Array{
int n,m,x[N],y[N],H[N],SA[N],cnt[N],rank[N],Height[N];char s[N];
//Suf[i]: s[i,n]
//len: 已经求出了长度为len的串的排名
//x[i]: Suf[i]的排名 (排序第一关键字) (上一次排序后得到的rank[i])
//y[i]: 按第len个字符排出来的顺序(排序第二关键字) (第二关键字排名为i的数的位置)
//H[i]: H[i]=Height[rank[i]] 即 LCP(Suf[i],Suf[SA[rank[i]-1]])
//SA[i]: 排名为i的后缀第一个字符所在位置
//cnt[i]: 第一关键字排名为 i(1~i)的数有多少个
//rank[i]: Suf[i]的排名
//Height[i]: Height[i]=H[SA[i]] 即 LCP(Suf[SA[i]],Suf[SA[i-1]])
inline void get_SA(){
m=128;
memset(cnt, 0, sizeof cnt);
memset(rank, 0, sizeof rank);
for(int i=1;i<=n;++i)++cnt[x[i]=s[i]];
for(int i=2;i<=m;++i)cnt[i]+=cnt[i-1];
for(int i=n;i>=1;--i)SA[cnt[x[i]]--]=i;
for(int len=1;len<=n;len<<=1){
int t=0;
for(int i=n-len+1;i<=n;++i)y[++t]=i;
for(int i=1;i<=n;++i)if(SA[i]>len)y[++t]=SA[i]-len;
for(int i=1;i<=m;++i)cnt[i]=0;
for(int i=1;i<=n;++i)++cnt[x[i]];
for(int i=2;i<=m;++i)cnt[i]+=cnt[i-1];
for(int i=n;i>=1;--i)SA[cnt[x[y[i]]]--]=y[i],y[i]=0;
swap(x,y);
x[SA[1]]=m=1;//把旧的x存进了y并清零x
for(int i=2;i<=n;++i)
x[SA[i]]=(y[SA[i]]==y[SA[i-1]]&&y[SA[i]+len]==y[SA[i-1]+len])?m:++m;//注意这里的SA[i]+len和SA[i-1]+len有可能访问到n+1,所以上面的N最好稍开大一点,不要尝试卡这点小常数空间
if(m==n)break;
}
}
inline void get_Height(){
for(int i=1;i<=n;++i)rank[SA[i]]=i;
for(int i=1,k=0;i<=n;++i){
if(rank[i]==1)continue;
if(k)--k;//H[i-1]-1<=H[i]
int j=SA[rank[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])++k;
Height[rank[i]]=k;
}
// for(int i=1;i<=n;++i)printf("%d ",Height[i]);
}
}SA;
void solve() {
cin >> (SA.s + 1);
SA.n = strlen(SA.s + 1);
SA.get_SA();
SA.get_Height();
}
signed main() {
ll t = 1;//cin >> t;
while (t--) {
solve();
}
}