首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    回文子串的个数_统计回文子串的个数

    (1)从左往右,钉住最后一个字符。 “abaa”串:先考查中心子串“ba”不是回文串,就可以判定“abaa”不是回文子串; “baa”串:先考查中心子串“baa”不是回文,它是最外子串,不必向外扩散; “aa”串:考查中心子串中“aa”是回文,它是最外子串,不必向外扩散。 (2)从右边倒数第二个字符往左,钉住第一个字符。 “aba”串:考查中心子串“aba”,是回文,它是最外子串,不必向外扩展; “ab”串:考查子串“ab”,不是回文,它是最外子串,不必向外扩展; 这样下来,加上单个子串“a”,“b”,“a”,“a”4个,“abaa”中共包含6个回文子串。 1.2、输入描述 输入数据中有多个测试案例。每个案例是一个非空且长度不超过5000的字符串。 处理到文件结尾。 1.3、输出描述 在每行上打印该字符串中回文子串的个数。 1.4、输入样例 aba aa 1.5、输出样例 4 3 2、C++实现 #include <iostream> using namespace std; int main(int argc, char* argv[]) { char s[5000]; int p, i, Half, Left, Right, Count; while( cin>>s ) { i = strlen(s); Count = 0; //从左到右钉住最后一个 for(p=0; p<=i-1; p++) { Half = ((i-1)-p) / 2; //如果子串是奇数个 if( ((i-1)-p)%2 == 0 ) { Left = p + Half - 1; Right = p + Half + 1; } else { //如果子串是偶数个 Left = p + Half; Right = p + Half + 1; } while(Left >= p) { if( s[Left] == s[Right]) { Count++; //发现了一个回文串 Left--; Right++; } else { //如果不相等,立即终止,由中心向外扩散不可能会有回文串 break; } } } //从右到左钉住第一个 for(p=i-2; p>=1; p--) { Half = p / 2; //如果子串是奇数个 if(p%2 == 0) { Left = Half - 1; Right = Half + 1; } else //如果子串是偶数个 { Left = Half; Right = Half + 1; } while( Left >= 0 ) { if( s[Left] == s[Right] ) { Count++; //发现了一个回文串 Left--; Right++; } else { //如果不相等,立即终止,由中心向外扩散不可能会有回文串 break; } } } printf("%d\n",Count + i); } return 0; }

    02

    动态规划之最长回文子串

    还是先看暴力解法:枚举子串的两个端点i和j,判断在[i, j]区间内的子串是否回文。从复杂度上来看,枚举端点需要0(n2),判断回文需要0(n),因此总复杂度是O(n3)。终于碰到一个暴力复杂度不是指数级别的问题了!但是O(n)的复杂度在n很大的情况依旧不够看。 可能会有读者想把这个问题转换为最长公共子序列(LCS) 问题来求解:把字符串S倒过来变成字符串T,然后对S和T进行LCS模型求解,得到的结果就是需要的答案。而事实上这种做法是错误的,因为一旦S中同时存在一个子串和它的倒序,那么答案就会出错。例如字符串S= “ABCDZJUDCBA”,将其倒过来之后会变成T = “ABCDUJZDCBA”,这样得到最长公共子串为”ABCD”,长度为4,而事实上S的最长回文子串长度为1。因此这样的做法是不行的。 动态规划解决 令dp[i][j]表示S[i]至S[j]所表示的子串是否是回文子串,是则为1,不是为0。这样根据S[i]是否等于S[j],可以把转移情况分为两类: ①若S[i]=S[j],那么只要S[i+1]和S[j-1]是回文子串,S[i+1]至S[j-1]就是回文子串;如果S[i+1]至S[j-1]不是回文子串,则S[i]至S[j]一定不是回文子串。 ②若S[i]!=S[j],那S[i]至S[j]一定不是回文子串。 由此可以写出状态转移方程

    05
    领券