牛客网编程小结(一)——回文序列

来源:互联网 发布:达内java培训怎么样 编辑:程序博客网 时间:2024/05/21 06:54
回文序列
如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, 
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
现在给出一个数字序列,允许使用一种转换操作:
选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和)。
现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。
输入描述:
输入为两行,第一行为序列长度n ( 1 ≤ n ≤ 50)第二行为序列中的n个整数item[i] (1 ≤ iteam[i] ≤ 1000),以空格分隔。
输出描述:
输出一个数,表示最少需要的转换次数
输入例子:
41 1 1 3
输出例子:
2
例一、
#include "stdafx.h"#include<iostream>#include<vector>using namespace std;int comb(int* num,int head,int tail){int times=0;int left=num[head],right=num[tail];while(head<tail&&left!=right){if(left<right){left=left+num[++head];times++;}else{right=right+num[--tail];times++;}}if(head>=tail)return times;else{times=times+comb(num,head+1,tail-1);return times;}}int _tmain(int argc, _TCHAR* argv[]){int n;cin>>n;int item[50]={0};for(int i=0;i<n;i++){cin>>item[i];}cout<<comb(item,0,n-1)<<endl;return 0;}
例二、
#include "stdafx.h"#include<iostream>#include<vector>using namespace std;int fun(vector<int> arr){int head=0;int tail=arr.size()-1;int times=0;int left=arr[head];int right=arr[tail];while(head<tail){if(left==right){left=arr[++head];right=arr[--tail];}else if(left<right){left=left+arr[++head];times++;}else if(left>right){times++;right=right+arr[--tail];}}return times;}int _tmain(int argc, _TCHAR* argv[]){int n;cin>>n;vector<int> item(n);for(int i=0;i<n;i++)cin>>item[i];cout<<fun(item)<<endl;return 0;}
统计回文
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。花花非常喜欢这种拥有对称美的回文串,生日的时候她得到两个礼物分别是字符串A和字符串B。现在她非常好奇有没有办法将字符串B插入字符串A使产生的字符串是一个回文串。你接受花花的请求,帮助她寻找有多少种插入办法可以使新串是一个回文串。如果字符串B插入的位置不同就考虑为不一样的办法。
例如:
A = “aba”,B = “b”。这里有4种把B插入A的办法:
* 在A的第一个字母之前: "baba" 不是回文
* 在第一个字母‘a’之后: "abba" 是回文
* 在字母‘b’之后: "abba" 是回文
* 在第二个字母'a'之后 "abab" 不是回文
所以满足条件的答案为2
输入描述:
每组输入数据共两行。第一行为字符串A第二行为字符串B字符串长度均小于100且只包含小写字母
输出描述:
输出一个数字,表示把字符串B插入字符串A之后构成一个回文串的方法数
输入例子:
abab
输出例子:
2
#include<iostream>#include<string>using namespace std;bool huiwen(string str){int len=str.length();for(int i=0;i<len;i++){if(str[i]!=str[len-1])return false;len--;}return true;}int main(){string str1,str2,temp;int count;while(cin>>str1>>str2){count=0;int len2=str1.length();for(int i=0;i<=len2;i++){temp=str1;temp.insert(i,str2);if(huiwen(temp))count++;}cout<<count<<endl;}return 0;}
构造回文
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入描述:输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.输出描述:对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子:
abcdagoogle
输出例子:
22
提到回文串,自然要利用回文串的特点,想到将源字符串逆转后,“回文串”(不一定连续)相当于顺序没变,求原字符串和其反串的最大公共子序列(不是子串,因为可以不连续)的长度(使用动态规划很容易求得),然后用原字符串的长度减去这个最大公共子串的长度就得到了最小编辑长度。
#include<iostream>#include<string>#include<math.h>#include<algorithm>using namespace std;const int MAX=1001;//MaxLen[i][j]int MaxLen[MAX][MAX];int maxLen(string str1,string str2){    int len1=str1.size();    int len2=str2.size();    for(int i=0;i<len1;i++)        MaxLen[i][0]=0;    for(int i=0;i<len2;i++)        MaxLen[0][i]=0;    for (int i=1;i<=len1;i++)    {        for(int j=1;j<=len2;j++)        {            if(str1[i-1]==str2[j-1])                MaxLen[i][j]=MaxLen[i-1][j-1]+1;            else                MaxLen[i][j]=max(MaxLen[i-1][j],MaxLen[i][j-1]);        }    }    return MaxLen[len1][len2];}int main(){    string s;    while(cin>>s)    {        int len=s.size();        string s2=s;        reverse(s2.begin(),s2.end());        int max_length=maxLen(s,s2);        cout<<len-max_length<<endl;    }}