蓝桥杯每日一题
前言
一、题目
问题描述
二、解题
1.思路
第一想法肯定会想到KMP的next数组。但这回人家问的是最短的有效前后缀长度。但比KMP简单的是,s1是由s2至少两次完整复制过来的。要知道前缀必定是从第一位开始的字符串,后缀一定是最后一位往前的字符串。我们可以想象一下s1会长什么样:
s2+s2+s2的一部分(空白也是)
那s2前面还会有字符串吗?
不可能有,因为会导致s2改变。
举个例子:
abcabca的前后缀是abca,s2是abc
cabcabca前后缀是ca,s2是ca
那问题就好做了,最长前后缀是大于或等于s2的(反证法可以证明),而前后缀大于s2的条件是:前缀形状会是s2+s2残缺,后缀形状会是s2(这个s2是用着前缀的残缺s2做开头补足的完整s2)+s2残缺。整个s1-前缀或者s1-后缀剩下的会是什么?上面已经提到过s1=s2+s2+s2残缺了,减法得出s2+s2+s2残缺-s2+s2残缺=s2!此时我们可以直接得到s2。
2.代码
#include<string>
#include<iostream>
using namespace std;
int main() {
int s1;
cin >> s1;
string s2;
cin >> s2;
//模式串建立
int kmp[100000000];
kmp[0]=0;
int i=0;
int j=1;
for(j=1;j<s2.size();j++){
while(i&&s2[i]!=s2[j])i=kmp[i-1];
if(s2[i]==s2[j]){
i++;
}
kmp[j]=i;
}
cout<<s1-kmp[s1-1];
return 0;
}
总结
写代码题没思路往往是盯着要算的问题太久了,其实题目信息可以转换成其他信息帮助我们联通到答案,冷静分析所有会出现可能,其实和以前做数学题感觉一模一样,先转换信息,然后再分类讨论。