这节难度很大,有很多处理方法都可以消化
第一题:oj里面的1085,题目是处理环状序列,主要知识点就是关于string的应用,一个是把字符串延长做法一个是关于取子串做法,需要做的是学习string
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
string s;
scanf("%d",&t);
while(t--)
{
cin>>s;
string s2,smin;
smin=s;
int len=s.size();
s+=s;
for(int i=0;i<len;i++)
{
s2=s.substr(i,len);
if(s2<smin) smin=s2;
}
cout<<smin<<endl;
}
return 0;
}
下一题是oj重复子序列1039问题
这个题难度很大,有一个重要知识点要记,序列自动机,以及为了方便序列自动机做出的改动
#include<bits/stdc++.h>
using namespace std;
#define N 100005
int main()
{
int st[N][26];
char a[N],b[N];
while(scanf("%s%s",a+1,b)!=EOF) //这个a+1处理技巧,目的是让序列自动机好用
{
int len=strlen(a+1); //从1到len的意思
for(int i=0;i<26;i++)st[len][i]=0; //最后一个位置什么也没有
for(int i=len;i>0;i--) //序列自动机,很重要思想,后面有很多事实上类似的处理
{
for(int j=0;j<26;j++)
//保留上个位置状态
st[i-1][j]=st[i][j];
st[i-1][a[i]-'a']=i;
}
int ans=1;int l=strlen(b);int j=0;
//int k=0;
for(j=0;j<l;j++) {
if(st[0][b[j]-'a']==0)break;
}
if(j<l) puts("-1");
else
{
int i=0; //a的下标是1,但是从0开始
for(j=0;j<l;j++)
{
i=st[i][b[j]-'a'];
if(i==0)
{
ans++;
i=st[i][b[j]-'a'];
}
}
}
printf("%d\n",ans);
/*while(j<l)
{
if(st[k][b[j]-'a']==0){
//ans=-1;
//cout<<"-1"<<endl;
break;
}
else
{
j++;
k=st[k][b[j]-'a']+1;
if(k>=len)
{
k=0;ans+=1;
}
}
}*/
//if(j<l)puts("-1");
//printf("%d\n",ans);
}
return 0;
}
第三题是1035出现连续字符串最大数目
此题是难题,主要方法有:前缀和
其中在最后的循环判断和ans的处理上出现问题,总结说就是细节分析情
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+3;
int st[N][26];
int main()
{
int k;
char s[N];
while(scanf("%d%s",&k,s)!=EOF)
{
int len=strlen(s);
for(int j=0;j<26;j++) st[0][j]=0;
for(int i=0;i<len;i++)
{
for(int j=0;j<26;j++) st[i+1][j]=st[i][j];
st[i+1][s[i]-'a']++;
}
int l=0,r=len,m;
int ans=0;
while(l<=r)
{
bool flag=0;
int i=0;
m=(l+r)>>1;
for(;i+m<=len;i++)
{
if(st[i+m][s[i]-'a']-st[i][s[i]-'a']+k>=m&&st[len][s[i]-'a']-st[0][s[i]-'a']>=m)
{
flag=1;break;
}
}
if(flag)
{
ans=m;l=m+1;
}
else r=m-1;
}
printf("%d\n",ans);
}
return 0;
}
第四题是1344 PIPI的字符串问题Ⅱ
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+3;
typedef unsigned long long ull;
const ull base=2333;
int main()
{
char t[N],s[N];
ull st[N];
scanf("%s%s",s,t);
int n=strlen(t),m=strlen(s); //t小s大
if(n>m) //这个条件判断也很重要
{
puts("NO");return 0;
}
//st[0]=s[0];
for(int i=1;i<=m;i++)
st[i]=s[i-1]+st[i-1]*base; //重点就是关于这个东西,前缀和
ull ht=0,p=1;
for(int i=0;i<n;i++) p=p*base; //基数
for(int i=0;i<n;i++)
ht=ht*base+t[i]; //计算综合与前缀和的区别
int ans=0;
for(int i=0;i+n<=m;i++)
{
if(st[i+n]-st[i]*p==ht)
{
ans++;
}
}
if(ans>0)
{
printf("YES\n%d\n",ans);
}
else
printf("NO\n");
return 0;
}
第五题1345: PIPI的字符串问题Ⅲ
这个提说明前缀和还是没了解完
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+3;
typedef unsigned long long ull;
ull st1[N],st2[N];
ull base=2333;
ull p[N];
int main()
{
char s[N];
scanf("%s",s);
int len=strlen(s);
for(int i=1;i<=len;i++)
st1[i]=st1[i-1]*base+s[i-1];
for(int i=len;i>0;i--)
st2[i-1]=st2[i]*base+s[i-1];
p[0]=1;
for(int i=1;i<=len;i++) p[i]=p[i-1]*base;
int q,m,n;
scanf("%d",&q);
while(q--)
{
scanf("%d %d",&m,&n);
// for(int i=0;i<m-n+1;i++) p=p*base;
ull w,e;
w=st1[n]-st1[m-1]*p[n-m+1],e=st2[m-1]-st2[n]*p[n-m+1];
if(w==e) printf("YES\n");
else printf("NO\n");
}
return 0;
}
第六题1351小鱼比可爱
较为简单的一道题
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+3;
int main()
{
int n;int a[N],b[N];
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int stack[N];int top=-1;
top++;
stack[top]=n; //站内存下标
b[n]=0; //最右边一定是0
for(int i=n-1;i>0;i--) //遍历n-1次
{
if(a[i]>=a[stack[top]])
{
while(a[i]>=a[stack[top]]&&top>=0) top--;
if(top==-1)
{
b[i]=0;
top++;
stack[top]=i;
}
else
{
b[i]=stack[top];
top++;
stack[top]=i;
}
}
else
{
b[i]=stack[top];
top++;
stack[top]=i;
}
}
for(int i=1;i<=n;i++) printf("%d ",b[i]);
printf("\n");
return 0;
}