题解 CF1766B Notepad#

大家好,我是 CQ-C2024 蒟蒻 CJH。

题意

给定一个字符串,有以下两个操作:

  • 在字符串的结尾添加任何一个字母。

  • 复制一个已经输入的字符串的连续子串,并将这个子串粘贴到字符串的结尾。

请用小于 $n$ 个操作,完成这个字符串。

分析

因为要小于 $n$ 次操作完成这个字符串,所以不可能每一次都添加单独一个字符或复制单独一个字符。

所以字符串必须要存在两个不重叠且长度大于 $1$ 的相同子串,这样才能保证可以少用一次操作就可以添加两个字符。

只需要用 map<string,int> 来记录每两个字符构成的子串第一次出现的位置,如果有出现过还需要判断这两个子串是否重叠。

注意事项

如果你的 map 定义在全局中,一定要清空多测不清空,爆零两行泪。

代码

//the code is from chenjh
#include<bits/stdc++.h>
using namespace std;
string s;
map<string,int> m;
void solve(){
    m.clear();//定义在全局中一定要清空!
    int n;scanf("%d",&n);
    cin>>s;
    string tmp;
    for(int i=0;i<n-1;i++){
        tmp=(char)s[i];
        tmp+=(char)s[i+1];//取出字符串的第 i 和 i+1 个字符,构成一个长度为 2 的子串。
        if(m.find(tmp)==m.end()) m[tmp]=i;//如果不存在这个字串则标记当前位置。
        else{
            if(m[tmp]!=i-1){//如果不重叠。
                puts("YES");
                return;
            }
        }
    }
    puts("NO");
}
int main(){
    int t;scanf("%d",&t);
    while(t--) solve();
    return 0;
}
posted @ 2022-12-16 09:39  Chen_Jinhui  阅读(13)  评论(0)    收藏  举报  来源