题目
求最长回文串
暴力
- 枚举所有点两两组合
- 判断两点之内是否是回文
- 枚举的时间复杂度是O(N ^ 2),判断的时间复杂度是O(N),所以暴力的方法时间复杂度为O(N ^ 3)
#include<cstdio> #include<string> #include<iostream> using namespace std; int main() { string str; getline(cin, str); int ans = 1; for (int i = 0; i < str.size(); i++) { for (int j = i + 1; j < str.size(); j++) { int start = i, end = j; int temp = 0; while (str[start] == str[end] && start <= end) { start++; end--; } if (start >= end) temp = j - i + 1; if (temp > ans) ans = temp; } } printf("%d", ans); }
注
只有一个字符的时候,也是回文结构且回文长度为1,所以ans要初始化为1。
动态规划
动态规划做法是找到状态转移方程。
- 令dp[i][j]来表示i,j之间的串是否为回文串,则如果str[i] == str[j] && dp[i + 1][j - 1] == 1,就能保证当前i,j的串也是回文结构。
- 一开始所有的dp[i][i]都是1,然后可既得的更新就是dp[i][i + 1],这是可以直接初始化处理得到的
- 然后针对不同的长度进行判断,所以设定长度L作为外循环变量
- 设定了L,则内循环中判断的子串长度是相同的,只是判断他们是否为回文结构,这样就可以使得长度4使用长度3的结论,使状态可以顺利转移不漏判。
#include<cstdio> #include<string> #include<iostream> #include<algorithm> using namespace std; const int maxn = 1010; int dp[maxn][maxn]; int main() { string str; getline(cin, str); int ans = 1; fill(dp[0], dp[0] + maxn * maxn, 0); for (int i = 0; i < str.size(); i++) { dp[i][i] = 1; if (i < str.size() - 1) { if (str[i] == str[i + 1]) { dp[i][i + 1] = 1; ans = 2; } } } for (int L = 3; L <= str.size(); L++) { for (int i = 0; i + L - 1 < str.size(); i++) { int j = i + L - 1; if (str[i] == str[j] && dp[i + 1][j - 1] == 1) { ans = L; dp[i][j] = 1; } } } printf("%d", ans); return 0; }