题目描述
给你两个只由小写字母组成的字符串S,T,保证S的长度大于等于T,现在你必须删除T串中一个字符,使得T串变成S串的子串,输出删除的位置,如果有多个位置合法,输出最小的那个,如果没有合法的位置,输出-1
输入描述:
第一行输入字符串S(2 <= |S| <= 3e5)
第二行输入字符串T(2 <= |T| <= S)
输出描述:
输出一个数
示例1
输入
复制
aaaab
aabaa
输出
复制
3
示例2
输入
复制
aaaa
aaa
输出
复制
1
示例3
输入
复制
abcd
xyz
输出
复制
-1
思路
简单哈希,把s串中连续长度为len_t-1的子串转化成相应数值,存到map里;再把t串中例举拿掉每个字符,把拿掉一个字符的子串转化为数值,若map中存在该值则找到合法答案了。
题解
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
char s[maxn],t[maxn];
long long base[3]={0,23,29},mod[3]={0,100000000+7,100000000+9},h[3][maxn],f[3][maxn];
map<long long,int >mp_1,mp_2;
long long ksm(long long res,long long cnt,long long mo)
{
long long sum=1;
while(cnt>0)
{
if(cnt&1)sum=(sum*res)%mo;
res=(res*res)%mo;
cnt>>=1;
}
return sum;
}
int main()
{
//memset(h,0,sizeof(h));
//memset(f,0,sizeof(f));
scanf("%s%s",s+1,t+1);
int len_s=strlen(s+1);
int len_t=strlen(t+1);
for(int i=1;i<=len_s;i++)
{
for(int k=1;k<=2;k++)
h[k][i]=(h[k][i-1]*base[k]+s[i]-'a'+1)%mod[k];
}
long long res[3];
for(int i=len_t-1;i<=len_s;i++)
{
for(int k=1;k<=2;k++)
res[k]=(h[k][i]-h[k][i-len_t+1]*ksm(base[k],len_t-1,mod[k])%mod[k]+mod[k])%mod[k];
mp_1[res[1]]=1;
mp_2[res[2]]=1;
}
for(int i=1;i<=len_t;i++)
{
for(int k=1;k<=2;k++)
f[k][i]=(f[k][i-1]*base[k]+t[i]-'a'+1)%mod[k];
}
for(int i=1;i<=len_t;i++)
{
for(int k=1;k<=2;k++)
res[k]=(f[k][len_t]-f[k][i]*ksm(base[k],len_t-i,mod[k])%mod[k]
+f[k][i-1]*ksm(base[k],len_t-i,mod[k])%mod[k]+mod[k])%mod[k];
if(mp_1[res[1]]==1&&mp_2[res[2]]==1)
{
cout<<i;
return 0;
}
}
cout<<-1<<endl;
}