1、构造回文
时间限制:1秒
空间限制:32768K
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子1:
abcda google
输出例子1:
2 2
解法一:
分析:先求字符串s的反串reverse,然后求它们的最长的公共子序列,就能知道要删除的字符个数了。
C++程序如下:
#include <iostream> #include <string.h> #include <algorithm> using namespace std; const int MAXN=1010; //定义一个整型常量MAXN int temp[MAXN][MAXN]; //声明一个数组temp int getRemoveNumber(string &s1) { string s2(s1); reverse(s2.begin(),s2.end()); //翻转s2 int len=s1.length(); //s1的长度 memset(temp,0,sizeof temp); //将temp所指向的某一块内存中的前(sizeof temp)个字节的内容全部设置为0 for(int i=0;i<len;++i) { for(int j=0;j<len;++j) { if(s1[i]==s2[j]) temp[i+1][j+1]=temp[i][j]+1; else temp[i+1][j+1]=max(temp[i][j+1],temp[i+1][j]); } } return len-temp[len][len]; } int main() { string s; while(cin>>s) { cout<<getRemoveNumber(s)<<endl; } return 0; }
【相关函数介绍】
memset函数:
函数原型: memset(void *s,int ch,size_t n)
函数说明:
memset函数是计算机中C/C++语言函数。将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值,第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为指向s的指针。所在头文件<memory.h>或<string.h>。
该函数的第二个参数ch为进行初始化的值,该值的范围为0到255(00000000到11111111)。如果超过该范围那么会对该值取后8位。如果ch为字符型,那么取其ASCII码。
1.对bool数组进行初始化:初始化结果为true或false
(1)使用 0或1初始化 memset(prime,0,sizeof(prime));0为false,1为true
(2)使用 true或false初始化 memset(prime,true,sizeof(prime));true为true,false为false
(3)使用其它值初始化 memset(prime,‘A’,sizeof(prime)); 非0值为true,0为false(字符0取ASCII码48,为true)
2.对char数组进行初始化:
(1)使用char型变量。memset(CH,‘A’,sizeof(CH));初始化结果为对应的字符。
(2)使用int型变量。将该int值作为ASCII码,使用对应的字符进行初始化。(0到127为ASCII码表,其中0为NULL,128到254未知,应该为扩展ASCII码。255显示字符串中字符无效。)
(3)使用bool型变量true或false。(true为ASCII码1,false为ASCII码0,初始结果同int)
3.对int数组进行初始化:
仅可在初始化的值的最后8位为11111111(255)或00000000(0)时能够正确进行初始化。也就是说int型数组仅能初始化为-1和0。其余方法均不能得到正确的结果。
解法二:
分析:本题可以转换为求该字符串与其反序字符串的最长公共子序列问题,即利用LCS算法求解。
例如:abcda
的反序字符串为adcba
,最长公共子序列为aba
,其公共子序列必为回文序列,然后可求出最少删除多少个字节使其成为回文字符串。
本题采用动态规划来求解问题,下面看看模拟的推导过程。
状态转移方程为:(令A为输入字符串,B为其反序字符串,num[][]记录当前最长公共子序列的长度)
if (A[i] == B[j]) num[i][j] = num[i-1][j-1] + 1
else num[i][j] = max(num[i-1][j] , num[i][j-1])
C++程序如下:
#include <stdio.h> #include <iostream> #include <string.h> #include <vector> #include <string> using namespace std; int main(){ string s; while(cin>>s){ int len = s.length(); int maxlen = 0; vector<vector<int> > Vec; for(int i = 0 ; i < len+1 ; i++){ vector<int> temp(len+1,0); Vec.push_back(temp); } for(int i = 1; i< len+1 ; i++){ for(int j = 1 ; j < len+1;j++){ if(s[i-1]==s[len-j]){ Vec[i][j] = Vec[i-1][j-1]+1; } else { Vec[i][j] = max(Vec[i-1][j],Vec[i][j-1]); } } } cout<<len-Vec[len][len]<<endl; } }
2、字符移位
时间限制:1秒
空间限制:32768K
小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
你能帮帮小Q吗?
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出移位后的字符串。
示例1
输入AkleBiCeilD
输出kleieilABCD
分析:如果碰到大写,就插入到字符串的最后面.
C++程序如下:
#include <iostream> #include <string.h> using namespace std; int main() { char a[1000]; while(cin>>a) { int len = strlen(a); int end = len-1; for(int i = 0; i<= end;) { if(a[i]>='A'&&a[i]<='Z') { char temp = a[i]; for(int j=i; j<len; j++) { a[j]=a[j+1]; } a[len-1] = temp; end--; } else i++; } cout<<a<<endl; } return 0; }
有趣的数字
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,相差最小的有多少对呢?相差最大呢?
时间限制:1秒
空间限制:32768K
输入描述:
输入包含多组测试数据。 对于每组测试数据: N - 本组测试数据有n个数 a1,a2...an - 需要计算的数据 保证: 1<=N<=100000,0<=ai<=INT_MAX.
输出描述:
对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。
示例1
输入6
45 12 45 32 5 6
输出1 2
分析:先排序,然后对有序数组分别求差值最大的对数和差值最小的对数。排序之后,差值最大的好求,看有序数组有几个最小值和几个最大值,相乘即可。差值最小的,由于是有序数组,必定是相邻的差值较小,故由排序后的有序数组求出差值最小值。如果差值最小值为0,则算出数组中相等的元素的对数;如果差值最小值不为0,则只需计算有多少个最小值即可。
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int n; while (cin>>n) { vector<int> nums(n); for (int i=0; i<n; i++) { cin>>nums[i]; } int minNum=0, maxNum=0; //排序 sort(nums.begin(), nums.end()); //最大 int m1 = 0, m2 = n-1, a=1, b=1; while (nums[m1+1] == nums[m1]) { a++; m1++; } while (nums[m2] == nums[m2-1]) { b++; m2--; } maxNum = a*b; //最小 int minTemp=nums[n-1]; for (int i=1; i<n; i++) { if (nums[i]-nums[i-1]<minTemp) { minTemp = nums[i]-nums[i-1]; } } if (minTemp >0) { for (int i=1; i<n; i++) { if (nums[i]-nums[i-1] == minTemp) { minNum++; } } }else{ for (int i=1; i<n; i++) { int j=i-1; while (nums[j]==nums[i] && j>=0) { minNum++; j--; } } } cout<<minNum<<" "<<maxNum<<endl; } return 0; }