洛谷题单 【算法2-4】字符串

P3375 【模板】KMP

https://www.luogu.com.cn/problem/P3375

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<bits/stdc++.h>
using namespace std;
using u32 = unsigned;
#define i128 __int128;
using ll = long long;
//#define int ll
using u64 = unsigned long long;
const ll inf = 1e9;
const ll INF = 1e18;
const int N=1e6+10;
int ne[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s1,s2;
cin>>s1>>s2;
int n=s1.size(),m=s2.size();
for(int i=1,j=0;i<m;i++)
{
while(j&&s2[i]!=s2[j])j=ne[j];
if(s2[i]==s2[j])j++;
ne[i+1]=j;
}
for(int i=0,j=0;i<n;i++)
{
while(j&&s1[i]!=s2[j])j=ne[j];
if(s1[i]==s2[j])j++;
if(j==m)
{
cout<<i-m+1+1<<'\n';
}
}
for(int i=1;i<=m;i++)
{
cout<<ne[i]<<" \n"[i==m];
}

return 0;
}

P4391 [BOI2009] Radio Transmission 无线传输

https://www.luogu.com.cn/problem/P4391

image-20250121230320552

所以推出:

1. 因为上下对应相等,故第1段等于红色段;

2. 因为是公共前后缀,故第2段等于第1段;

3. 因为上下对应相等,故第3段等于第2段;

4. 因为是公共前后缀,故第4段等于第3段;

5. ……

6. 红色段就是循环子串;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<bits/stdc++.h>
using namespace std;
using u32 = unsigned;
#define i128 __int128;
using ll = long long;
//#define int ll
using u64 = unsigned long long;
const ll inf = 1e9;
const ll INF = 1e18;
const int N=1e6+10;
int ne[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
string s;
cin>>s;
for(int i=1,j=0;i<n;i++)
{
while(j&&s[i]!=s[j])j=ne[j];
if(s[i]==s[j])j++;
ne[i+1]=j;
}
cout<<n-ne[n]<<'\n';

return 0;
}