基本的回文串练习(区间dp来做)

这道题的标签很简单,就是一道入门题。但是我发现,这道题其实是可以用dp来做的.
首先,把题目放上来:

题目描述

给定一个字符串,输出所有长度至少为2的回文子串。
回文子串即从左往右输出和从右往左输出结果是一样的字符串,比如:abba,cccdeedccc都是回文字符串。

样例输入

123321125775165561

样例输出

33
11
77
55
2332
2112
5775
6556
123321
165561

我们首先定义状态:

dp[i][j] 为 i ~ j 的区间是否为回文串

所以我的 dp 数组是布尔的。
首先我们做一下预处理,如下:

for (int i = 1; i <= n; i++) {
	dp[i][i] = 1;
}

因为每一个字符它本身一定是回文的
然后我们就可以用两重循环跑一遍,更新我们的dp

for (int i = 1; i <= n; i++) {
	for (int j = 1; j < i; j++) {/*每次只用跑到i前面就可以,i 后面之后会更
    新,而 dp[i][i] 本身就是1,不用管*/
		if (a[i] == a[j]) {/*第i个到第j个有可能构成回文串*/
			if ((dp[i - 1][j + 1] == 1) || (j + 1 == i)) {/*第一个判断的是i到j的中间的一个区间是不是
            回文的因为在一个回文串的两边加上两个相同的字也一定是回文的呀*/
            /*第二个是判断i和j相邻的情况,此处不再赘述*/
				dp[i][j] = 1;/*说明满足条件,i ~ j 之间也是回文的。*/
			} 
		}
	}
}

这样,我们就可以找出所有的回文串了**(其实也挺简单)**
然后,因为题目是要求我们 : 回文子串即从左往右输出和从右往左输出结果是一样的字符串
所以,我们再用循环来找出答案:

for (int i = 1; i < n; i++) {
	int l = 0, r = i;//就像用一个框框去框一个固定大小的区间,
	while (r < n) {
		if (dp[++r][++l] == 1) {//找到答案,输出
			for (int k = l; k <= r; k++) {
				printf("%c", a[k]);
			}
			printf("\n");
		}
	}
}

好了,文章就到这里了,要是有写的不好的地方请不吝赐教

你可能感兴趣的:(区间dp)