kuangbin帶你飛:點擊進入新世界
三四個月之前挖的字符串坑:kmp初學狀態 黑歷史
迴文串:不懂馬拉車的可以點這裏
總結:
本人算是初學者中的初學者,歡迎交流~
先試試字符串的水。
部分題目是之前考覈的時候做的,那時候理解不深,邊看題解邊寫的,現在爭取重新做,碼風有兩種,帶快讀和萬能頭的是現在做的。2019.11.24。
舊題已重新過一遍,準備做新題。2019.11.25
- kmp的話重點考察對next數組的理解,next[i]是指回滾到上一次匹配的位置,可以發現每次回滾的長度都是 j-next[j] 。所以當有循環節
(n%(n−next[n])==0 && next[n] != 0)的時候,n-next[n]便是最小的循環節長度,循環次數便是 n / ( n - next[n] ) 。 - Manacher主要是理解其求最大回文串的思想。
kuangbin之外:
kmp模板:點擊進入新世界
馬拉車算法模板:不懂馬拉車的可以點這裏
文章目錄
1.Number Sequence
原題鏈接:傳送門
思路:
- kmp模板題,把字符數組換成數字數組 。
代碼如下:
#include<bits/stdc++.h>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll a[manx],b[manx],nexts[manx];
ll n,m;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || b[i]==b[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
ll kmp()
{
getnexts();
int i=0,j=0;
while(i<n && j<m){
if( j==-1 || a[i]==b[j] ) ++i,++j;
else j=nexts[j];
}
if(j==m) return i-j+1;
else return -1;
}
int main()
{
ll p=read();
while(p--)
{
n=read(),m=read();
for(int i=0;i<n;i++) a[i]=read();
for(int i=0;i<m;i++) b[i]=read();
cout<<kmp()<<endl;
}
return 0;
}
2.Oulipo
原題鏈接:傳送門
思路:
- 模板題。
- 匹配完一圈繼續回到 next[j] 的位置,見代碼註釋處。
代碼如下:
#include<bits/stdc++.h>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#define stdd std::ios::sync_with_stdio(false)
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
ll kmp()
{
getnexts();
int i=0,j=0,ans=0;
while(i<n ){
if( j==-1 || s[i]==p[j] ) ++i,++j;
else j=nexts[j];
if(j==m) ans++,j=nexts[j]; // 匹配結束後讓j回滾就可以了
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>p>>s;
m=p.size(),n=s.size();
cout<<kmp()<<endl;
}
return 0;
}
3.剪花布條
原題鏈接:傳送門
思路:
- 模板題,計算出現次數,這種情況跟上一題差不多,不過要使j匹配結束後回到0的位置,見代碼註釋處。
代碼如下:
#include<bits/stdc++.h>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#define stdd std::ios::sync_with_stdio(false)
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m,ans;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
ll kmp()
{
getnexts();
int i=0,j=0,ans=0;
while(i<n && j<m){
if( j==-1 || s[i]==p[j] ) ++i,++j;
else j=nexts[j];
if(j==m) ans++,j=0; //就是這裏,匹配結束後要重置j
}
return ans;
}
int main()
{
stdd;
while(cin>>s)
{
if(s[0]=='#') break;
cin>>p;
m=p.size(),n=s.size();
cout<<kmp()<<endl;
}
return 0;
}
4.Cyclic Nacklace
原題鏈接:傳送門
思路:
- 考察對next數組的理解:週期性字符串循環節長度 ans 是 n−next[n] ,也可以理解爲 n-next 的前綴是最小覆蓋子串 ,而當前提爲n% ans==0&&next[n] !=0時,循環次數是 n/ans 。
- 實在不懂可以翻本文章的開頭有解析,或者私信,歡迎交流。
代碼如下:
#include<bits/stdc++.h>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e5+5;
ll nexts[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--)
{
cin>>p;
m=p.size();
getnexts();
ll len=m-nexts[m];
if(len!=m && m%len==0) cout<<0<<endl;
else cout<<len-m%len<<endl;
}
return 0;
}
5.Count the string
原題鏈接:傳送門
思路:
- 這道題是求所以前綴出現的次數和。
- 要深刻理解next數組,當i匹配失敗的時候會回到next[i]的位置,所以當前串包含了next[i]所包含的前綴數+其當前本身,所以可以得到狀態轉移方程:
- dp[i] = dp[ next[i] ] +1
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=2e5+5;
ll nexts[manx],dp[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--)
{
cin>>m>>p;
getnexts();
ans=0;
for(int i=1;i<=m;i++)
dp[i]=(dp[nexts[i]]+1)%10007,ans=(dp[i]+ans)%10007;
cout<<ans<<endl;
}
return 0;
}
6. Simpsons’ Hidden Talents
原題鏈接:傳送門
思路:
- 求最大公共s1前綴和s2後綴,可以把兩個串連在一起,再用nexts數組來做。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx],m,n;
string s,p;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
while(cin>>p)
{
cin>>s;
ll l1=p.size(),l2=s.size();
p=p+s;
m=p.size();
getnexts();
ll ans=nexts[m];
while(ans>l1||ans>l2) ans=nexts[ans];
if(ans==0) cout<<0<<endl;
else {
for(int i=0;i<ans;i++) cout<<p[i];
cout<<" "<<ans<<endl;
}
}
return 0;
}
7.Blue Jeans
原題鏈接:傳送門
思路:
- 暴力匹配,取第一個串爲模式串,暴力枚舉每個子串是否在其他串中出現過。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e4+5;
string s[manx];
int main()
{
ll t=read();
while(t--)
{
ll n=read();
string b="";
for(int i=0;i<n;i++) cin>>s[i];
for(int i=0;i<=60;i++)
for(int j=0;j<60;j++)
{
ll flag=1;
string p=s[0].substr(j,i);
for(int k=1;k<n;k++)
if(s[k].find(p)==string::npos){
flag=0;
break;
}
if(flag) {
if(p.size()>b.size()) b=p;
else if(p.size()==b.size()&&p<b) b=p;
}
}
if(b.size()<3) cout<<"no significant commonalities"<<endl;
else cout<<b<<endl;
}
return 0;
}
8.Power Strings
原題鏈接:傳送門
思路:
- 考察對next數組的理解:週期性字符串循環節長度 ans 是 n−next[n] ,也可以理解爲 n-next 的前綴是最小覆蓋子串 ,而當前提爲n% ans==0&&next[n] !=0時,循環次數是 n/ans 。
- 實在不懂可以翻本文章的開頭有解析,或者私信,歡迎交流。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
while(cin>>p)
{
if(p[0]=='.') break;
m=p.size();
getnexts();
ll len=m-nexts[m];
if(len!=m && m%len==0 ) cout<<m/len<<endl;
else cout<<1<<endl;
}
return 0;
}
9. 最長迴文
原題鏈接:傳送門
思路:
- manacher模板題 沒什麼好說的 。
- 迴文串:不懂馬拉車的可以點這裏
- 注意取消cin和cout的同步性。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
string manacher(string s1)
{
string s="$#";
for(int i=0;i<s1.size();i++)
s+=s1[i],s+="#";
vector<int>p(s.size(),0);
int id=0,mx=0,maxpoint=0,maxlen=0;
for(int i=1;i<s.size();i++){
p[i]=mx>i+p[i]?min(mx-i,p[2*id-i]):1;
while(s[i+p[i]]==s[i-p[i]]) ++p[i];
if(i+p[i]>mx) id=i,mx=i+p[i];
if(p[i]>maxlen) maxlen=p[i],maxpoint=i;
}
return s1.substr( (maxpoint-maxlen)/2 , maxlen-1) ;
}
int main()
{
string s;
std::ios::sync_with_stdio(false);
while(cin>>s)
{
s=manacher(s);
cout<<s.size()<<endl;
}
return 0;
}
10. Girls’ research
原題鏈接:傳送門
思路:
- Manacher模板題 。
- 迴文串:不懂馬拉車的可以點這裏
- s1.substr( (maxpoint-maxlen)/2, maxlen-1) 是截取最大回文串,那麼 (maxpoint-maxlen)/2 就是迴文串的起始位置 , 長度爲maxlen-1 ,那麼可以知道結束位置=起始位置+長度-1=(maxpoint-maxlen)/2+maxlen-2。
- 注意取消cin和cout的同步性。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
void manacher(string s1)
{
string s="$#";
for(int i=0;i<s1.size();i++)
s+=s1[i],s+="#";
vector<int>p(s.size(),0);
int id=0,mx=0,maxpoint=0,maxlen=0;
for(int i=1;i<s.size();i++){
p[i]=mx>i+p[i]?min(mx-i,p[2*id-i]):1;
while(s[i+p[i]]==s[i-p[i]]) ++p[i];
if(i+p[i]>mx) id=i,mx=i+p[i];
if(p[i]>maxlen) maxlen=p[i],maxpoint=i;
}
if(maxlen>3){
cout<<(maxpoint-maxlen)/2<<" "<<(maxpoint-maxlen)/2+maxlen-2<<endl;
cout<<s1.substr( (maxpoint-maxlen)/2 , maxlen-1)<<endl;
}
else puts("No solution!");
}
int main()
{
string s;
char c;
int ans;
std::ios::sync_with_stdio(false);
while(cin>>c>>s)
{
ans=c-'a';
for(int i=0;i<s.size();i++)
if(s[i]>=c) s[i]=s[i]-ans;
else s[i]=s[i]+26-ans;
manacher(s);
}
return 0;
}
11. Palindrome
原題鏈接:傳送門
思路:
- Manacher模板題 ,跟模板一模一樣,不懂的可以點下面這個。
- 迴文串:不懂馬拉車的可以點這裏
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
string manacher(string s1)
{
string s="$#";
for(int i=0;i<s1.size();i++)
s+=s1[i],s+="#";
vector<int>p(s.size(),0);
int id=0,mx=0,maxpoint=0,maxlen=0;
for(int i=1;i<s.size();i++){
p[i]=mx>i+p[i]?min(mx-i,p[2*id-i]):1;
while(s[i+p[i]]==s[i-p[i]]) ++p[i];
if(i+p[i]>mx) id=i,mx=i+p[i];
if(p[i]>maxlen) maxlen=p[i],maxpoint=i;
}
return s1.substr( (maxpoint-maxlen)/2 , maxlen-1) ;
}
int main()
{
int t=1;
string s;
while(cin>>s)
{
if(s=="END") break;
s=manacher(s);
cout<<"Case "<<t++<<": "<<s.size()<<endl;
}
return 0;
}
12. Theme Section
原題鏈接:傳送門
思路:
- kmp思維題,由next數組可得nexts[m]爲最長的公共前後綴,再暴力枚舉即可。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e7+5;
ll nexts[manx];
string s,p;
ll n,m;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ll t=read();
while(t--)
{
cin>>p;
m=p.size();
getnexts();
int len=nexts[m];
while(len*3>m) len--;
while(len)
{
string s1=p.substr(0,len),s2=p.substr(len,m-2*len);
if(s2.find(s1)==string::npos) len--;
else break;
}
cout<<len<<endl;
}
return 0;
}
13. 吉哥系列故事——完美隊形II
原題鏈接:傳送門
思路:
- manacher模板題 。
- 迴文串:不懂馬拉車的可以點這裏
- 注意s[i-p[i]]<=s[i-p[i]+2] 保持隊列左邊遞增,這樣迴文對稱右邊就遞減了。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll a[manx],n;
ll manacher()
{
vector<ll>s;
s.push_back(-1);
s.push_back(0);
for(int i=0;i<n;i++)
s.push_back(a[i]),s.push_back(0);
vector<int>p(s.size(),0);
int id=0,mx=0,maxpoint=0,maxlen=0;
for(int i=1;i<s.size();i++){
p[i]=mx>i+p[i]?min(mx-i,p[2*id-i]):1;
while(s[i+p[i]]==s[i-p[i]]&&s[i-p[i]]<=s[i-p[i]+2]) ++p[i];
if(i+p[i]>mx) id=i,mx=i+p[i];
if(p[i]>maxlen) maxlen=p[i],maxpoint=i;
}
return maxlen-1;
}
int main()
{
ll t=read();
while(t--)
{
n=read();
for(int i=0;i<n;i++) a[i]=read();
cout<<manacher()<<endl;
}
return 0;
}
14. Substrings
原題鏈接:傳送門
思路:
- 跟第七題類似,可以參考一下第七題的思路,不過多了一個反轉串的判斷。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e4+5;
string s[manx];
int main()
{
ll t=read();
while(t--)
{
ll n=read(),ans=0;
for(int i=0;i<n;i++) cin>>s[i];
for(int i=0;i<=s[0].size();i++)
for(int j=0;j<s[0].size();j++)
{
ll flag=1;
string p=s[0].substr(j,i);
string t=p;
reverse(p.begin(),p.end());
for(int k=1;k<n;k++)
if(s[k].find(p)==string::npos&&s[k].find(t)==string::npos){
flag=0;
break;
}
ll res=max(p.size(),t.size());
if(flag) ans=ans>res?ans:res;
}
cout<<ans<<endl;
}
return 0;
}
15. Wow! Such Doge!
原題鏈接:傳送門
思路:
- 水題,暴力枚舉判斷即可。
代碼如下:
//#include<bits/stdc++.h>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e7+5;
int main()
{
string s;
ll ans=0;
while(cin>>s)
{
for(int i=0;i<s.size();i++)
if(s[i]=='D'||s[i]=='d')
if(s[i+1]=='o'||s[i+1]=='O')
if(s[i+2]=='g'||s[i+2]=='G')
if(s[i+3]=='e'||s[i+3]=='E')
ans++;
}
cout<<ans<<endl;
return 0;
}
16. Period
原題鏈接:傳送門
思路:
- 考察next數組,由於next數組的儲存原理,需要從下標等於2開始枚舉。
代碼如下:
//#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#include<string>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m;
string p;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
int n=1;
while(scanf("%64d",&m)!=EOF)
{
if(m==0) break;
cin>>p;
getnexts();
printf("Test case #%d\n",n++);
for(int i=2;i<=m;i++)
if( i%(i-nexts[i])==0 && i/(i-nexts[i])>1 )
printf("%d %d\n",i,i/(i-nexts[i]));
printf("\n");
}
return 0;
}
17. Seek the Name, Seek the Fame
原題鏈接:傳送門
思路:
- 考察next數組,next[i]表示最大的前後綴相同長度,所以從最後面開始枚舉。
代碼如下:
//#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#include<string>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m;
string p;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
while(cin>>p)
{
m=p.size();
getnexts();
vector<ll>ans;
ans.clear();
while(m>0){
ans.push_back(m);
m=nexts[m];
}
for(int i=ans.size()-1;i>=0;i--)
cout<<ans[i]<<" ";
cout<<endl;
}
return 0;
}
18. Corporate Identity
原題鏈接:傳送門
思路:
- 跟第七題類似,暴力枚舉即可。
代碼如下:
//#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#include<string>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e4+5;
string s[manx];
int main()
{
IOS;
int n;
while(cin>>n&&n)
{
string ans="";
for(int i=0;i<n;i++) cin>>s[i];
for(int i=0;i<=s[0].size();i++)
for(int j=0;j<s[0].size();j++)
{
ll flag=1;
string p=s[0].substr(j,i);
for(int k=1;k<n;k++)
{
if(s[k].find(p)==string::npos)
{
flag=0;
break;
}
}
if(flag){
if(p.size()>ans.size()) ans=p;
else if(p.size()==ans.size()&&ans>p) ans=p;
}
}
if(ans.size()>0) cout<<ans<<endl;
else cout<<"IDENTITY LOST"<<endl;
}
return 0;
}