Strings in the Pocket
题目大意:
建议不会马拉车的朋友先去看看马拉车算法在来看看这题,如果会的话请往下看。
首先会给你一个数字n表示有n组测试用例,每组测试用例有两个字符串。要求是把一个字符串中的一部分反转使其与第二个字符串相等。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <cstring>
#include <queue>
typedef long long ll;
using namespace std;
string q,w,t;
int p[4000020];
ll manacher() {
t="$";
for(int a=0; a<q.length(); a++) {
t+="#";
t+=q[a];
}
t+="#@";
for(int a=0; a<t.length(); a++)p[a]=0;
ll re=0;
int mx=0,id=0;
for(int a=1; a< t.length()-1; a++) {
if(a<mx)p[a]=min(mx-a,p[2*id-a]);
else p[a]=1;
while(t[a-p[a]]==t[a+p[a]])p[a]++;
if(a+p[a]>mx)mx=a+p[a],id=a;
re+=p[a]/2;
}
return re;
}
int n;
int main() {
ios::sync_with_stdio(false);//此行和下一行用来加快输入输出
cin.tie(0);
while(cin>>n) {
while(n--) {
cin>>q>>w;
int len=q.length();
ll ans=0;
if(q!=w) { //判断两个字符串是否相等
int st=len+1;
int en=-1;
for(int a=0; a<len; a++) { //找出不同串的起点
if(q[a]!=w[a]) {
st=a;
break;
}
}
for(int a=len-1; a>=0; a--) { //找出不同串的终点
if(q[a]!=w[a]) {
en=a;
break;
}
}
bool ok=1;
for(int a=st; a<=en; a++) { //判断不同的串是否可以通过反转来变得相同
if(q[a]!=w[en-(a-st)]) {
ok=0;
break;
}
}
if(ok) {//如果可以的话给ans赋值,并往两边找回文的长度
ans=1;
int j=1;
while(st-j>=0&&en+j<len&&q[st-j]==q[en+j]) {//往两边你找回文的长度
ans++;
j++;
}
}
} else {
ans=manacher();
}
cout<<ans<<endl;
}
}
return 0;
}
代码思路:
我把这题分为两个情况:
1:当两个字符串相等的时候,如果两个字符串相等的话,就是在这个字符串中找出所有的回文串的数量就是简单的马拉车
2:当这连个字符串不一样的时候,首先要判断这连个字符串中不相等的部分是否可以通过反转来使者两个字符串相关等,如果不行答案就是0;否则从不行等的位置开始往两端扩散着找看看他两端有多少是对称的,这一部分在反转后仍然相等,所以答案就是对称部分的长度加上1(自身)。
感觉其实这题只要可以想到找回文,并且会马拉车算法的话其实不难。
趁年轻,别给自己后悔的机会,错过了就什么都来不及了。