把字符串中某字符串换为其他字符
getline(cin,s)可以输入带空格的整行字符串。
getline(cin,line,’#’);终止条件是输入“#”,you are the best #one 读入为you are the best
两个字符串相差2,所以引入t,记录相差多少,每次起点处减掉。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
int main()
{
string s,s1,s2,ans;
s1="marshtomp";
s2="fjxmlhx";
int j;
while(getline(cin,s)&&s[0]!='\0')//输入整行
{
ans=s;j=0;
for(int i=0;i<ans.length();i++)
{
ans[i]=tolower(ans[i]);
}
int node=0,t=0;
while(node<ans.length())
{
j=ans.find(s1,node);//字符串,起始位置
if(j==-1) break;
else
{
s.replace(j-2*t,9,s2);t++;//更换起点,长度,更换为字符串
node=j+9;
}
}
cout<<s<<endl;
}
return 0;
}
把一串字符 给定长度的前缀和后缀 修改为相同的
把需要相同的字符分为一组,每组中都改为众数最大的那个字符。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
int main()
{
int t,k,count,l,mx,cishu;
string s;
scanf("%d",&t);
while(t--)
{
cin>>s;count=0;
scanf("%d",&k);
int len=s.length();
if(len>=k*2)
{
for(int i=0;i<k;i++)
{
if(s[i]!=s[i+len-k]) count++;
}
}
else
{
for(int i=0;i<len-k;i++)
{
map<char,int> m;
l=i;mx=0;cishu=0;
while(l<len)
{
m[s[l]]++; mx=max(mx,m[s[l]]); l=l+len-k;cishu++;
}
count=count+cishu-mx;
}
}
printf("%d\n",count);
}
return 0;
}
给你两个由小写英文字母组成字符串s,t。如果s[i…i+|t|-1] = t (|t|表示t的长度),则认为s[i…i+|t|-1] 是t的相等串。现在有q次询问,每次询问你s[L..R]中有多少个不同位置的t的相等串。
用数组a[ ]记录该位置后多少位形成一个字符串t,初始化所有位置,最后判断时尾部减掉t的长度
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
ll a[100005];
ll n,m,q,c,b,l;
string s,t;
void fun()
{
int j;
for(int i=0;i<=n-m;i++)
{
if(s[i]==t[0])
{
for(j=1;j<m;j++)
{
if(s[i+j]!=t[j]) break;
}
if(j==m) a[i]=1;
}
}
}
int main()
{
ll count;
scanf("%lld%lld%lld",&n,&m,&q);
cin>>s;
cin>>t;
memset(a,0,sizeof(a));
fun();
while(q--)
{
scanf("%lld%lld",&c,&b);
count=0;
for(int i=c-1;i<=b-m;i++)
{
if(a[i]) count++;
}
printf("%lld\n",count);
}
return 0;
}
KMP寻找子串首次出现的位置
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
int a[1000005];
int b[10005];
int ne[10005];
int m,n;
void getnext()
{
int i=0,j=-1;
ne[0]=-1;
while(i<m)
{
if(j==-1||b[i]==b[j])
{
i++;j++;ne[i]=j;
}
else j=ne[j];
}
}
int index()
{
int i=0,j=0;
getnext();
while(i<n&&j<m)
{
if(j==-1||a[i]==b[j])
{
i++;j++;
}
else j=ne[j];
}
if(j==m) return i-m+1;
else return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
printf("%d\n",index());
}
return 0;
}
模式串在待匹配字符串中出现次数
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1000010;
char a[10010],b[maxn];
int ne[10010];
int mu,zi,t;
void getnext()
{
ne[0]=-1;
int i=0,j=-1;
while(i<zi)
{
if(j==-1||b[i]==b[j])
{
i++;j++;ne[i]=j;
}
else j=ne[j];
}
}
int count()
{
getnext();
int ct=0,j=0,i=0;
while(i<mu)
{
while(j&&a[j]!=b[i])
{
j=ne[j];
}
if(a[j]==b[i]) j++;
if(j==zi)
{
ct++;j=ne[j];
}
i++;
}
return ct;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s%s",&a,&b);
zi=strlen(a);mu=strlen(b);
printf("%d\n",count());
}
return 0;
}
求字符串中相同前后缀的长度
字符串s的前缀是指,从s的开始字符到s的任意字符为止的子串。字符串s的后缀是指,从s的任意字符到s的最后字符为止的子串。s是既是自身的前缀也是自身的后缀。
这个问题利用KMP算法的next[]数组来解。首先对于输入的字符串s,计算其next[]数组。然后,根据next[]数组的值进行进一步的计算。对于字符串s的第i个字符s[i],next[i]定义为字符s[i]前面最多有多少个连续的字符和字符串s从初始位置开始的字符匹配。
从后到前匹配前缀和后缀。如果前缀与后缀匹配,则下一个前缀与后缀匹配的字符串只能在前缀中。
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=400005;
int ne[maxn],a[maxn];
int len;
string s;
void getnext()
{
int i=0,j=-1;
ne[0]=-1;
while(i<len)
{
if(j==-1||s[i]==s[j])
{
i++;j++;
ne[i]=j;
}
else j=ne[j];
}
}
int main()
{
while(cin>>s&&s!="NULL")
{
len=s.size();
getnext();
int t=ne[len-1],cnt=0;
while(t!=-1)
{
if(s[t]==s[len-1]) a[cnt++]=t+1;
t=ne[t];
}
for(int i=cnt-1;i>=0;i--)
printf("%d ",a[i]);
printf("%d\n",len);
}
return 0;
}
找循环节,至少添加多少个字符形成循环字符
len-next[ len ]为最小循环节!!!
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
char a[maxn];
int ne[maxn];
int t,len,zu;
void getnext()
{
int i=0,j=-1;
ne[0]=-1;
while(i<=len)
{
if(j==-1||a[i]==a[j])
{
i++;j++;ne[i]=j;
}
else j=ne[j];
}
}
int main()
{
scanf("%d",&t);
getchar();
while(t--)
{
scanf("%s",&a);
len=strlen(a);
getnext();
zu=len-ne[len];
if(len==zu) printf("%d\n",len);
else if(len%zu==0) printf("0\n");
else printf("%d\n",zu-len%zu);
}
return 0;
}
给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值。
对每一个前缀出现的次数都叠加到其包含的前缀当中去,即状态转移方程 d[Next[i]] += d[i] ( d[i]代表长度为 i 的前缀出现的次数)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=100005;
ll ne[maxn];
ll num[maxn];
char s[maxn];
ll len;
void get_next()
{
ll i=0,j=-1;
ne[0]=-1;
while(i<len)
{
if(j==-1||s[i]==s[j])
{
i++;j++;
ne[i]=j;
}
else j=ne[j];
}
}
int main()
{
scanf("%s",&s);
len = strlen(s);
get_next();
ll mx=0;
memset(num,0,sizeof(num));
for(ll i=len;i>0;i--)
{
num[i]++;
num[ne[i]]+=num[i];
mx=max(mx,num[i]*i);
}
printf("%lld\n",mx);
return 0;
}