Strings in the Pocket(2019年 16届浙江省省赛 K题)manacher

Strings in the Pocket(题目链接)

题意:

输入2个串s1、s2,翻转区间s1(l, r)使s1=s2,限定(r>=l),问可翻转区间个数

思路:

分类讨论:

1、存在不相同字符

步骤:① 找到存在不相同字符的最大区间,验证s1和s2在该区间内的对称性

           ② 如果满足对称性则向两边扩散,统计个数

复杂度:O(n)

2、不存在相同字符,即s1 = s2

其实就是求s1串的回文串总个数,跑一遍马拉车(manacher)板子

复杂度:O(n)

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long

char s1[2000005], s2[2000005];
// 构造字符串数组 
char s_new[4000005];
// 
int len[4000005];

// 构造马拉车数组 
int init(char str[])
{
	// 加了会超时 
	//memset(len, 0, sizeof(len));
    int n=strlen(str);
    for(int i=1,j=0;i<=2*n;j++,i+=2)
    {
        s_new[i]='#';
        s_new[i+1]=str[j];
    }
    s_new[0]='$';
    s_new[2*n+1]='#';
    s_new[2*n+2]='@';
    s_new[2*n+3]='\n';
    return 2*n+1;
}

// 求回文个数 
ll manacher(int n)
{
	ll ans = 0;
    int mx=0,p=0;
    for(int i=1;i<=n;i++)
    {
        if(mx>i)len[i]=min(mx-i,len[2*p-i]);
        else len[i]=1;
        while(s_new[i-len[i]]==s_new[i+len[i]])len[i]++;
        if(len[i]+i>mx)mx=len[i]+i,p=i;
        ans += (ll)len[i]/2;
    }
    return ans;
}

int min(int x, int y)
{
	if(x>y)
		return y;
	return x;
}

int max(int x, int y)
{
	if(x>y)
		return x;
	return y;
}

int main()
{
	int t ;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%s%s", s1, s2);
		int len_s1 = strlen(s1);
		int s, e, flag = 0;
		s = len_s1, e = 0;
		for(int i=0; i<len_s1; i++)
		{
			if(s1[i] != s2[i])
			{
				flag = 1;
				// 找到第一个不相同的位置
				s = min(s, i);
				// 找到最后一个不相同的位置 
				e = max(e, i);
			}
		}
		// 存在不相等区间
		if(flag)
		{
			bool ymk = true;
			int l = s, r = e;
			int p = r-l+1;
			// 验证不相等区间的对称性 
			while(p--)
			{
				if(s1[l] != s2[r])
				{
					ymk = false;
					break;
				}
				l++, r--;
			}
			// 不对称直接退出 
			if(!ymk)
			{
				printf("0\n");
				continue;
			}
			ll ans = 1;
			s--, e++;
			// 如果对称需要向两边扩散 
			while(1)
			{
				// 坐标约束 
				if(s<0 || e>=len_s1)
					break;
				// 对称性约束 
				if(s1[s] == s2[e] && s1[e] == s2[s])
				{
					ans++;
					s--, e++;
				}
				else
					break;
			}
			printf("%lld\n", ans);
		}
		// s1 = s2,跑一遍马拉车求回文个数 
		else
		{
			printf("%lld\n", manacher(init(s1)));
		}
	}
} 

笔者水平有限,若有错误欢迎纠正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Here's a possible C++ program to solve the problem: ```c++ #include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream infile("SortedStrings.txt"); string prev_str, curr_str; bool sorted = true; // read the first string from the file if (getline(infile, prev_str)) { // read the rest of the strings and check if they are in ascending order while (getline(infile, curr_str)) { if (curr_str < prev_str) { sorted = false; cout << "The strings in the file are not sorted in ascending order.\n"; cout << "The first two out-of-order strings are:\n"; cout << prev_str << endl << curr_str << endl; break; } prev_str = curr_str; } } if (sorted) { cout << "The strings in the file are sorted in ascending order.\n"; } infile.close(); return 0; } ``` In this program, we first open the file "SortedStrings.txt" using an ifstream object. We then read the first string from the file using getline() function, and store it in the variable prev_str. We then start reading the rest of the strings from the file using another getline() function, and compare each string with the previous string. If we find a string that is smaller than the previous string, we set the sorted flag to false, and display the first two out-of-order strings. Otherwise, we continue reading the file until the end, and if all strings are sorted, we display a message indicating that the strings are sorted in ascending order. Note that in this program, we have used the string class to store the strings read from the file, and the < operator to compare two strings. This is possible because the string class overloads the < operator to perform lexicographic comparison of two strings.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值