Strings in the Pocket ZOJ - 4110 (manacher)

版权声明: https://blog.csdn.net/nucleare/article/details/89709716

Strings in the Pocket

 ZOJ - 4110

BaoBao has just found two strings  and  in his left pocket, where  indicates the -th character in string , and  indicates the -th character in string .

As BaoBao is bored, he decides to select a substring of  and reverse it. Formally speaking, he can select two integers  and  such that  and change the string to .

In how many ways can BaoBao change  to  using the above operation exactly once? Let  be an operation which reverses the substring , and  be an operation which reverses the substring . These two operations are considered different, if  or .

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains a string  (), while the second line contains another string  (). Both strings are composed of lower-cased English letters.

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

2
abcbcdcbd
abcdcbcbd
abc
abc

Sample Output

3
3

Hint

For the first sample test case, BaoBao can do one of the following three operations: (2, 8), (3, 7) or (4, 6).

For the second sample test case, BaoBao can do one of the following three operations: (1, 1), (2, 2) or (3, 3).

https://www.cnblogs.com/whdsunny/p/10785922.html

题意:

存在S串和T串 要求对S串的一个子串做一次翻转操作可以得到T串的方案数

思路:

对子串分两种情况

第一种是S串和T串完全相同 可以的方案数就是S串中的所有的回文子串 因为S串长度为2e6 必须要用马拉车线性去处理出所有的回文子串

第二种是S串和T串有不同的部分 找出两个不同的字符最远的位置(l,r) 先判断S串的这个区间是否能通过翻转变成T串的区间 如果不可以直接输出0 如果可以 则向两侧同时延展寻找是否可以翻转

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
const int N = 4e6 + 7;
char s1[N], s2[N], s[N];
int p[N];
int init(int len) {
	s[0] = '$', s[1] = '#';
	int leng = 1;
	for (int i = 1; i <= len; ++i) {
		s[++leng] = s1[i];
		s[++leng] = '#';
	}
	s[++leng] = '@';
	s[++leng] = '\0';
	return leng-2;
}
void manacher(int len) {
	int id = 0, mx = 0;
	for (int i = 1; i <= len; ++i) {
		p[i] = i < mx ? min(p[2*id-i], mx-i) : 1;
		while (s[i + p[i]] == s[i - p[i]]) ++p[i];
		if (mx < i + p[i]) mx = i + p[i], id = i;
	}
}

int main() {
	
	int t;
	scanf ("%d", &t);
	while (t--) {
		scanf ("%s %s", s1+1, s2+1);
		int len = strlen(s1+1), pos1 = -1, pos2 = -1;
		for (int i = 1; i <= len; ++i) {
			if (s1[i] != s2[i]) {
				pos1 = i; break;
			} 
		}
		for (int i = len; i >= 1; --i) {
			if (s1[i] != s2[i]) {
				pos2 = i; break;
			}
		}
		if (pos1 == -1) {
			len = init(len);
			manacher(len);
			long long ans = 0;
			for (int i = 1; i <= len; ++i) ans += p[i]/2;
			printf ("%lld\n", ans);
		} else {
			int flag = 1;
			for (int i = pos1; i <= pos2; ++i) {
				if (s1[i] != s2[pos2 - (i-pos1)]) {
					flag = 0; break;
				}
			}
			if (!flag) {
				puts("0");
			} else {
				long long ans = 0;
				while (s1[pos1] == s2[pos2] && s1[pos2] == s2[pos1] && pos1 >= 1 && pos2 <= len) {
					--pos1, ++pos2, ++ans;
				}
				printf ("%lld\n", ans);
			}
		}
		
	}
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/nucleare/article/details/89709716
今日推荐