题目描述
阿福最近对回文串产生了非常浓厚的兴趣。
如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串。例如,abcaacba
是一个回文串,abcaaba
则不是一个回文串。
阿福现在强迫症发作,看到什么字符串都想要把它变成回文的。阿福可以通过切割字符串,使得切割完之后得到的子串都是回文的。
现在阿福想知道他最少切割多少次就可以达到目的。例如,对于字符串 abaacca
,最少切割一次,就可以得到 aba
和 acca
这两个回文子串。
输入
输入的第一行是一个整数 TTT (T≤20)(T \le 20)(T≤20) ,表示一共有 TTT 组数据。 接下来的 TTT 行,每一行都包含了一个长度不超过的 100010001000 的字符串,且字符串只包含了小写字母。
输出
对于每组数据,输出一行。该行包含一个整数,表示阿福最少切割的次数,使得切割完得到的子串都是回文的。
输入输出样例
样例输入 #1
3
abaacca
abcd
abcba
样例输出 #1
1
3
0
提示
对于第一组样例,阿福最少切割 111 次,将原串切割为 aba
和 acca
两个回文子串。
对于第二组样例,阿福最少切割 333 次,将原串切割为 a
、b
、c
、d
这四个回文子串。
对于第三组样例,阿福不需要切割,原串本身就是一个回文串。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int f[N],a[N],n,res,m,t; bool vis[1010][1010]; string s; bool check(int st,int ed)//用于判断是不是回文串 { while(st<=ed){ if(s[st]==s[ed]) st++,ed--; else return false; } return true; } int main() { cin>>t; while(t--) { memset(f,1,sizeof f);//因为要求最小值,所以先初始化为最大 memset(vis,false,sizeof vis); cin>>s; res=s.size(); for(int i=0;i<res;i++) for(int j=i+1;j<res;j++) if(check(i,j)) vis[i][j]=true;//判断每个片段是否是回文串 f[1]=0;//第一个字符不需要切割也是,所以为0 for(int i=2;i<=res;i++) { if(vis[0][i-1]) f[i]=0;//如果在这之前的是回文串那么从这个点开始就不需要切割 else f[i]=f[i-1]+1;//否则+1,继续切割 for(int j=i;j>=1;j--) if(vis[j-1][i-1]) f[i]=min(f[i],f[j-1]+1);//然后从这之前再判断,有可能前面存在f=0,更新状态 } cout<<f[res]<<endl; } return 0; }
标签:切割,int,样例,阿福,字符串,回文 From: https://www.cnblogs.com/o-Sakurajimamai-o/p/17470820.html