亲亲串(dp)

来源:互联网 发布:苏豪控股网络 编辑:程序博客网 时间:2024/05/15 11:45

亲亲串

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述

如果有一个字符串,它的前半段等于它后半段,例如 abcabc,我们就叫这种字符串为“亲亲串”。

现在给你一个字符串(仅有大小写字母组成),可以在任意的位置添加任意个字符,使这个字符串成为一个“亲亲串”,最少需要添加多少个字符?

输入
第一行是一个整数N(0<N<=1000),表示有N组测试数据。
接下来有N行,每行有一个字符串,字符串的长度小于1000;
输出
对于每组测试数据输出一个整数,为最小添加字符数
样例输入
3abcbcaaaababcd
样例输出
114
#include <stdio.h>#include <string.h>#include <stdlib.h>/*动态规划,将字符串分成两段,然后计算至少添加多少个字符才能使这两段字符串相等将字符串分段时,是从串的中间向两边遍历,加了剪枝*/char data[1002];//存储输入数据int dp[1002][1002];//打表用//对于两个字符串arr1和arr2,计算出至少需要添加几个字符//arr1:要计算的第一个字符串//arr1_len:arr1的长度//arr2:要计算的第二个字符串//arr2_len:arr2的长度//return:至少添加字符的个数int find(char *arr1, int arr1_len, char *arr2, int arr2_len){int temp1, temp2;if(dp[arr1_len][arr2_len] != -1){//记忆化搜索return dp[arr1_len][arr2_len];}if(arr1_len == 0 || arr2_len == 0){dp[arr1_len][arr2_len] = arr1_len > arr2_len ? arr1_len : arr2_len;return dp[arr1_len][arr2_len];}if(arr1[0] == arr2[0]){dp[arr1_len][arr2_len] = find(arr1 + 1, arr1_len - 1, arr2 + 1, arr2_len - 1);}else{temp1 = find(arr1, arr1_len, arr2 + 1, arr2_len - 1);temp2 = find(arr1 + 1, arr1_len - 1, arr2, arr2_len);dp[arr1_len][arr2_len] = 1 + (temp1 < temp2 ? temp1 : temp2);}return dp[arr1_len][arr2_len];}int main(){int t ;int i = 1;//whileint data_len;//输入的字符串的长度int res;//要输出的结果int temp;//临时变量//freopen("in.txt", "r", stdin);scanf("%d%*c", &t);while(t --){scanf("%s", data);data_len = strlen(data);memset(dp, -1, sizeof(dp));res = find(data, data_len / 2, data + data_len / 2, data_len - data_len / 2);i = 1;//插入位置从中间向两边找,若从左到右会超时,i > res时需要添加的字符个数就一定会大于res,所以不需要继续遍历了while(i <= res && i <= data_len / 2){memset(dp, -1, sizeof(dp));temp = find(data, data_len / 2 + i, data + data_len / 2 + i, data_len - data_len / 2 - i);res = res < temp ? res : temp;memset(dp, -1, sizeof(dp));temp = find(data, data_len / 2 - i, data + data_len / 2 - i, data_len - data_len / 2 + i);res = res < temp ? res : temp;++ i;}printf("%d\n", res);}return 0;}







原创粉丝点击