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
- 2.Oulipo
- 3.剪花布条
- 4.Cyclic Nacklace
- 5.Count the string
- 6. Simpsons’ Hidden Talents
- 7.Blue Jeans
- 8.Power Strings
- 9. 最长回文
- 10. Girls' research
- 11. Palindrome
- 12. Theme Section
- 13. 吉哥系列故事——完美队形II
- 14. Substrings
- 15. Wow! Such Doge!
- 16. Period
- 17. Seek the Name, Seek the Fame
- 18. Corporate Identity
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;
}