昨天比较忙,今天抽空写一下,毕竟自己没做的太好(主要是因为刚面试回来,头极晕,肚子极饿等等),还是总结一下好。
第一题:字符串距离
题目:
给出两个相同长度的由字符
a
和b
构成的字符串,定义它们的距离为对应位置不同的字符的数量。如串”aab”
与串”aba”
的距离为2
;串”ba”
与串”aa”
的距离为1
;串”baa”
和串”baa”
的距离为0
。下面给出两个字符串S
与T
,其中S
的长度不小于T
的长度。我们用|S|
代表S
的长度,|T|
代表T
的长度,那么在S
中一共有|S|-|T|+1
个与T
长度相同的子串,现在你需要计算T
串与这些|S|-|T|+1
个子串的距离的和。
输入描述:
第一行包含一个字符串
S
。第二行包含一个字符串T
。S
和T
均由字符a
和b
组成,1 ≤ |T| ≤ |S| ≤105
。
输出描述:
输出对应的答案。
样例:
in: aab aba out: 2
in: aaabb bab out: 5
思路:看了第一眼竟然想到的是kmp算法。。。后来仔细思考,发现他这里存在一个每个字符的贡献问题,如果对S串进行逐位看的话,在【1,T 】的范围内,S串的字符与T串参与比较的数量增加直到等于T,然后中间部分一直是等于T的,最后的部分【S-T+1, S】的范围内,数量则是逐渐递减。然后可以动态维护一个数组cnt[2](如果题目换成了26个字母的话,就是cnt[26]),然后保存在S串当前位置,T串会参与比较的字符的对应数量,比如,S串的第五个位置有2个a,3个b,那么该位置对结果的贡献很显然可以再O(1)的时间内算出来,而这个动态数组的维护也是O(1),所以总复杂度只是O(n).
代码:
#include<iostream>
#include<fstream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
#include<utility>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
#define f(a, b) (a) > (b) ? (a) : (b)
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int INF = 1<<30;
const ll llINF = 1e18+999;
const int maxn = 1e5 + 5;
char s[maxn], t[maxn];
int main(int argc, char const *argv[]) {
scanf("%s%s", s, t);
int lens = strlen(s);
int lent = strlen(t);
int cnt[30];
memset(cnt, 0, sizeof(cnt));
long long ans = 0;
int window = 0;
int p = lens - lent, q = 0;
for (int i = 0; i < lens; i ++) {
if (q < lent) {
cnt[t[q] - 'a'] ++;
window ++;
q ++;
}
if (i > p) {
cnt[t[i - p - 1] - 'a'] --;
window --;
}
// cout << i << " " << max(0, i - p) << " " << q << " " << window << endl;
ans += 1ll * (window - cnt[s[i] - 'a']);
}
cout << ans << endl;
return 0;
}
第二题:数字字符
题目:
在十进制表示中,任意一个正整数都可以用字符
‘0’-‘9’
表示出来。但是当‘0’-‘9’
这些字符每种字符的数量有限时,可能有些正整数就无法表示出来了。比如你有两个‘1’
,一个‘2’
,那么你能表示出11,12,121
等等,但是无法表示出10,122,200
等数。
现在你手上拥有一些字符,它们都是‘0’-‘9’
的字符。你可以选出其中一些字符然后将它们组合成一个数字,那么你所无法组成的最小的正整数是多少?
输入描述:
第一行包含一个由字符
’0’-‘9’
组成的字符串,表示你可以使用的字符。1 ≤ 字符串长度 ≤ 1000
输出描述:
输出你所无法组成的最小正整数。
样例:
in: 55 out: 1
in: 123456789 out: 10
思路:首先提一下,不能用int存结果的。考试时候没有ac,是理解错了题。题中说的是不能凑出的最小的正整数,那么首先想到有两种贪心策略,其一优先取位数少的,第二优先取高位数小的。考试的时候就是这里搞错了,这里有一个很重要的地方,那就是答案一定是某一个数被重复了n次的,或者是1加上0被重复n次(因为不能出现前导0),这里想明白了,就很简单了,直接暴力统计,比较,打印就好了。
代码:
#include<iostream>
#include<fstream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
#include<utility>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
#define f(a, b) (a) > (b) ? (a) : (b)
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
const int mod = 1e9+7;
const int INF = 1<<30;
const ll llINF = 1e18+999;
char in[maxn];
int main(int argc, char const *argv[]) {
while(~scanf("%s", in))
{
int n = strlen(in), Count[10] = {0};
for(int i=0; i<n; i++)
Count[in[i]-'0']++;
Count[0]++;//0特殊,第一位不能出现
int minCount = maxn, value = 0;
for(int i=0; i<10; i++)
{
if(Count[i]<minCount)
{
minCount = Count[i];
value = i;
}
}
if(value == 0)//如果是0最少
{
cout<<1;
while(minCount--)
{
cout<<0;
}
}
else
{
minCount++;
while(minCount--)
cout<<value;
}
cout<<endl;
}
return 0;
}