字符串1
作业介绍
/*
kmp
给两个字符串a和b
求b在a中出现了几次,
b字符串的每一个前缀
最长前缀=最长后缀的长度
abcabfabc
a:0
ab:0
abc:0
abca:1
abcab:2
abcabf:0
abcabfa:1
abcabfab:2
abcabfabc:3
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
string a,b;
int nxt[N];
int main(){
cin>>a>>b;a="#"+a;b="#"+b;
int j = 0;
for(int i=2;i<b.size();i++){
while(j>0 && b[j+1]!=b[i])j = nxt[j];
if(b[j+1]==b[i])j++;
nxt[i] = j;
}
j = 0;
for(int i=1;i<a.size();i++){
while(j>0 && b[j+1]!=a[i])j=nxt[j];
if(b[j+1]==a[i])j++;
if(j==b.size()-1){
cout<<i-b.size()+2<<endl;
j = nxt[j];
}
}
for(int i=1;i<b.size();i++){
cout<<nxt[i]<<" ";
}
return 0;
}
/*
f[i]前i位的文本串是否可以被模式串构成
j
if(第i-j.size()~i是模式串j)
f[i] = f[i-j.size()]
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 205;
int nxt[N][15],book[N][200005];
int f[200005];
string s,str[N];
int main(){
int cnt = 0;
while(cin>>s){
if(s==".") break;
cnt++;
s = "#"+s;
str[cnt] = s;
int j = 0;
for(int i=2;i<s.size();i++){
while(j && s[j+1]!=s[i])j=nxt[cnt][j];
if(s[j+1]==s[i])j++;
nxt[cnt][i] = j;
}
}
s = "";
string x;
while(cin>>x){
s=s+x;
}
s = "#"+s;
for(int i=1;i<=cnt;i++){
int k = 0;
for(int j=1;j<s.size();j++){
while(k && str[i][k+1]!=s[j])k=nxt[i][k];
if(str[i][k+1]==s[j])k++;
if(k==str[i].size()-1){
book[i][j] = 1;
k = nxt[i][k];
}
}
}
f[0] = 1;
int res = 0;
for(int i=1;i<s.size();i++){
for(int j=1;j<=cnt;j++){
if(book[j][i]){
f[i] |= f[i-str[j].size()+1];
}
}
if(f[i])res = max(res,i);
}
cout<<res<<endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int n,nxt[N];
string s;
int main(){
cin>>n>>s;
s = "#"+s;
for(int j=0,i=2;i<s.size();i++){
while(j && s[j+1]!=s[i])j=nxt[j];
if(s[j+1]==s[i])j++;
nxt[i] = j;
}
for(int i=1;i<s.size();i++){
while(nxt[nxt[i]]!=0)nxt[i]=nxt[nxt[i]];
}
long long res = 0;
for(int i=1;i<s.size();i++){
//cout<<i<<" "<<i-nxt[i]<<endl;
if(nxt[i])
res+=i-nxt[i];
}
cout<<res<<endl;
return 0;
}
题目
认领作业后才可以查看作业内容。
- 状态
- 正在进行…
- 题目
- 8
- 开始时间
- 2026-5-16 0:00
- 截止时间
- 2026-5-24 23:59
- 可延期
- 24 小时