寒假集训1字符串专题

第一题 Let the Balloon Rise

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1001&cid=34727

用结构体或者map来统计某一颜色出现的最多次数

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
	int n;
	while (cin >> n&&n)
	{
		string s, b[1010], ans;
		int num, max = 0;
		map <string, int>mp;
		for (int i = 0; i < n; i++)
			cin >> s, mp[s]++, b[i] = s;   //统计单词出现次数 
		for (int i = 0; i < n; i++)
			if (mp[b[i]] > max)
				max = mp[b[i]], ans = b[i];
		cout << ans << endl;
	}
	return 0;
}

第二题 手机短号

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1002&cid=34727

用substr返回该手机号的后五位,输出6+该字串即可

#include<iostream>
#include<string>
using namespace std;
int main(){
	int n;
	cin >> n;
	while (n--)
	{
		string a;
		cin >> a;
		cout << "6" << a.substr(6) << endl;
	}
	return 0;
}

第三题Online Judge

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1003&cid=34727

将二次输入的数据中空格,换行,制表都去掉,再进行对比

来判断AC,PE,WA。如果原字符串相同则AC,若去掉空格,换行,制表后相同即PE,否则WA

#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main(){
	int t;
	cin >> t;
	getchar();
	while (t--)
	{
		string s, a[2], b[2]; //用a来表示原字符串,b来表示转化后的字符串 
		for (int i = 0; i < 2; i++){
			getline(cin, s);
			while (1){
				getline(cin, s);
				if (s != "END")
					a[i] += s + '\n';
				else break;
			}
			int len = a[i].size();
			for (int j = 0; j < len; j++)
				if (a[i][j] != '\t'&&a[i][j] != '\n'&&a[i][j] != ' ') //将空格,制表,换行去掉,其余字符加入b中 
					b[i] += a[i][j];
		}
		if (b[0] != b[1])  // 如果去掉空格制表换行后, 仍然不同即答案错误
			cout << "Wrong Answer" << endl;
		else 
			if (a[0] != a[1])  // 若去掉空格制表换行后, 但加上又不同即是格式错误
			cout << "Presentation Error" << endl;
		else
			cout << "Accepted" << endl;  // 都不满足即答案错误
	}
	return 0;
}

 

第四题 亲和串

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?cid=34727&pid=1004

将S1增加为原来的两份,再判断S2是否为其增加后的子串

#include<iostream>
#include<string>
using namespace std;
int main(){
	string a, b;
	while (cin >> a >> b)  // 将原串扩征两倍后, 即原串任意移动后的情况均可在新串中出现
	{
		if (a.size() < b.size())
			cout << "no" << endl;
		else
		{
			a = a + a;
			if (a.find(b) != -1)
				cout << "yes" << endl;
			else
				cout << "no" << endl;
		}
	}
	return 0;
}

第五题 Easier Done Than Said?

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1005&cid=34727

题目的意思就是输入一串密码,判断是否满足题目要求

要求即为必须含有一个元音字母,且不能有超过三个以及以上的连续元音字母和辅音字母

除了o和e外,其余字母不能有重复

#include<iostream>
#include<string>
using namespace std;
int vowel(char a){
	if (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
		return 1;
	return 0;
}
int main(){
	string a;
	while (cin >> a&&a != "end")
	{
		int flag1 = 0, flag2 = 1, count2 = 0, count1 = 0;
		int len = a.size();
		for (int i = 0; i < len; i++){
			if (vowel(a[i]) == 1)
				flag1 = 1;
			if (vowel(a[i]) == 1)
				count2 = 0, count1++;
			else 
				count2++, count1 = 0;
			if (count1 >= 3 || count2 >= 3)
				flag2 = 0;
		}
		for (int i = 1; i < len; i++)
			if (a[i] == a[i - 1] && a[i] != 'e'&&a[i] != 'o')
				flag2 = 0;
		if (flag1&&flag2)
			cout << '<' << a << '>' << " is acceptable." << endl;
		else 
			cout << '<' << a << '>' << " is not acceptable." << endl;
	}
	return 0;
}

第六题 壮志难酬

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1006&cid=34727

题意如题目

用find找出小数点出现的下标,再加上k即是所求,如果超出范围,输出0

#include<iostream>
using namespace std;
int main(){
	int t;
	cin >> t;
	while (t--)
	{
		string a;
		int k;
		cin >> a;
		cin >> k;
		if (a.size() - 1 - a.find('.') < k)
			cout << "0" << endl;
		else
			cout << a[a.find('.') + k] << endl;
	}
	return 0;
}

第七题 终曲

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1007&cid=34727

枚举的方法,把原串的子串枚举出来,把满足条件的子串存入set。

第一个长度为最短的即是要求条件的。

#include<iostream>
#include<algorithm>
#include<set>
#include<string>
using namespace std;
int main(){
    int t;
    cin >> t;
    string a, b, c;
    while (t--){
        string M;
        set<string>s;
        int min1 = 10000;
        cin >> a >> b >> c;
        if (a.find(b) == -1 || a.find(c) == -1)
            cout << "No" << endl;
        else
        {
            for (int i = 0; i < a.size(); i++)
                for (int z = a.size() - i; z >= 1; z--)
                {
                    int k = z;
                    string f = a.substr(i, z);
                    if (f.find(b) != -1 && f.find(c) != -1)
                        s.insert(f), min1 = min(min1, z);
                }
            for (auto &i:s)
                if (i.size() == min1)
                {
                    cout << i << endl;
                    break;
                }
        }
    }
    return 0;
}

第八题Substrings

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1008&cid=34727

跟第七题一样用枚举的方法,枚举的对象是最短字符串的子串,记录最长的子串长度

再更: 这题少加个等号..杭电数据水了。 这题可以用后缀数组来做, 将正串反串拼接, 并记录位置。

当然这题数据比较弱。暴力更好写。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		string a[110], b, c, d;
		cin >> n;
		cin >> a[0];
		b = a[0];
		for (int i = 1; i < n; i++)
		{
			cin >> a[i];
			if (a[i].size() < b.size())
				b = a[i]; //记录长度最短的字符串
		}
		int max = 0;
		for (int i = 0; i < b.size() - 1; i++)
			for (int z = b.size() - i; z >= 1; z--)
			{
				int sum = 0, k = z;
				d = c = b.substr(i, z);
				reverse(d.begin(), d.end());
				for (int j = 0; j < n; j++)
				{
					if (a[j].find(c) != -1 || a[j].find(d) != -1)
						sum++;
				}
				if (sum == n)
				{                //该子串需要满足为所有串的子串
					if (k > max)
						max = k;
				}
			}
		cout << max << endl;
	}
	return 0;
}

后缀数组:

//#include <bits/stdc++.h>
#include <time.h>
#include <string>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <functional>
#include <set>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
int str[N];
int record[N];
char s[N];
int vis[410];
int idx;
int cnt;
int n;
struct SA
{
	int n, r;
	int cnt[N];
	int sa[N];
	int tmp[N];
	int rak[N];
	int heig[N];
	void radix_sort(int* rk, int* tp)
	{
		memset(cnt, 0, sizeof cnt);
		for (int i = 1; i <= n; i++)
			cnt[rk[tp[i]]]++;
		for (int i = 1; i <= r; i++)
			cnt[i] += cnt[i - 1];
		for (int i = n; i >= 1; i--)
			sa[cnt[rk[tp[i]]]--] = tp[i];
	}
	void suffix()
	{
		int *rk = rak, *tp = tmp;
		for (int i = 1; i <= n; i++)
			rk[i] = str[i], tp[i] = i;
		r = 400;
		radix_sort(rk, tp);
		for (int l = 1, p = 0, i; p < n; l <<= 1, r = p)
		{
			p = 0;
			for (i = n - l + 1; i <= n; i++)
				tp[++p] = i;
			for (i = 1; i <= n; i++)
				if (sa[i] > l)
					++p, tp[p] = sa[i] - l;
			radix_sort(rk, tp);
			swap(rk, tp);
			rk[sa[1]] = 1;
			p = 1;
			for (i = 2; i <= n; i++)
			{
				if (tp[sa[i]] != tp[sa[i - 1]] || tp[sa[i] + l] != tp[sa[i - 1] + l])
					p++;
				rk[sa[i]] = p;
			}
		}
	}
	void get_heig()
	{
		for (int i = 1; i <= n; i++)
			rak[sa[i]] = i;
		int k = 0;
		for (int i = 1; i <= n; i++)
		{
			if (k)
				k--;
			int j = sa[rak[i] - 1];
			while (str[i + k] == str[j + k])
				k++;
			heig[rak[i]] = k;
		}
	}
}sa;
int id(int m)
{
	if (m % 2 == 0 && m)
		return m - 1;
	else
		if (m)
			return m + 1;
}
bool check(int mid)
{
	int cnt = 0;
	memset(vis, 0, sizeof vis);
	vis[0] = 1;
	if (!vis[record[sa.sa[1]]] && !vis[id(record[sa.sa[1]])])
	{
		cnt++;
		vis[record[sa.sa[1]]] = 1;
		vis[id(record[sa.sa[1]])] = 1;
	}
	int flag = 1;
	for (int i = 2; i <= sa.n; i++)
	{
		if (sa.heig[i] >= mid)
		{
			flag = 1;
			if (!vis[record[sa.sa[i]]] && !vis[id(record[sa.sa[i]])])
			{
				cnt++;
				vis[record[sa.sa[i]]] = 1;
				vis[id(record[sa.sa[i]])] = 1;
			}
		}
		else
		{
			cnt = 0;
			memset(vis, 0, sizeof vis);
			vis[0] = 1;
			if (!vis[record[sa.sa[i]]] && !vis[id(record[sa.sa[i]])])
			{
				vis[record[sa.sa[i]]] = 1;
				vis[id(record[sa.sa[i]])] = 1;
				cnt++;
			}
			flag = 0;
		}
		if (cnt == n && flag)
			return true;
	}
	return false;
}
void solve()
{
	int L = 0, R = idx, ans = 0;
	while (L <= R)
	{
		int mid = L + R >> 1;
		if (check(mid))
			L = mid + 1, ans = mid;
		else
			R = mid - 1;
	}
	cout << ans << endl;
}
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		memset(record, 0, sizeof record);
		idx = 0;
		int u = 0, le = 1;
		cin >> n;
		for (int i = 1; i <= n; i++)
		{
			scanf("%s", s + 1);
			int len = strlen(s + 1);
			for (int j = 1; j <= len; j++)
			{
				str[++idx] = s[j] + 200;
				record[idx] = le;
			}
			++le;
			str[++idx] = ++u;
			for (int j = len; j >= 1; j--)
			{
				str[++idx] = s[j] + 200;
				record[idx] = le;
			}
			++le;
			str[++idx] = ++u;
		}
		sa.n = idx;
		sa.suffix();
		sa.get_heig();
		solve();
	}
	return TIME;
}

第九题排序

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1009&cid=34727

题意如题目,用stringstream和string都可以做,这里写两种做法

string的做法

 

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int getnum(string a){
	int sum = 0;
	for (int i = 0; i < a.size(); i++)
		sum = sum * 10 + a[i] - '0';
	return sum;
}
int main(){
	string a;
	while (cin >> a)
	{
		int x = 0, k = 0, i = 0;
		int s[1010];
		if (a[0] == '5')
		{
			while (a[i] == '5')i++;      //将最前面的5抵消掉
		}
		k = i; //默认起始下标为第一个非5的字符
		if (a[a.size() - 1] != '5')s[x++] = getnum(a.substr(a.find_last_of('5') + 1));
		for (i = i + 1; i < a.size(); i++)
		{
			int flag = 0;
			if (a[i] == '5')s[x++] = getnum(a.substr(k, i - k)), flag = 1;//取被截取的子串存入数组
			while (a[i] == '5')i++;
			if (flag == 1)k = i;   //更新起始的下标
		}

		sort(s, s + x);         //将存入数组的数排序
		for (int i = 0; i < x; i++)
		{
			cout << s[i];
			if (i != x - 1)cout << " ";
		}
		cout << endl;
	}
	return 0;
}

stringstream的做法

#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
#include<string.h>
using namespace std;
int ans[1010];
int main(){
	string s;
	while (cin >> s)
	{
		memset(ans, 0, sizeof(ans));
		int len = s.size();
		for (int i = 0; i < len; i++)
			if (s[i] == '5')s[i] = ' '; // 将5变成空格, 用于下面的分割
		stringstream ss;
		ss << s;
		int x = 0;
		for (;;)
		{
			int b;
			ss >> b;
			if (ss.fail())
				break;
			ans[x++] = b;
		}
		sort(ans, ans + x);
		for (int i = 0; i < x; i++)
		{
			if (i == 0)
				cout << ans[0];
			else
				cout << " " << ans[i];
		}
		cout << endl;
	}
	return 0;
}

第十题:Telephone Numbers 

链接http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1010&cid=34727

时隔几个月, 再做这题, 还是没过呜呜

下面是最近写的代码。

嘤嘤嘤

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
using namespace std;
char r(char a){
    if (a == 'Q' || a == 'Z')return '1';
    if (a == 'A' || a == 'B' || a == 'C')return '2';
    if (a == 'D' || a == 'E' || a == 'F')return '3';
    if (a == 'G' || a == 'H' || a == 'I')return '4';
    if (a == 'J' || a == 'K' || a == 'L')return '5';
    if (a == 'M' || a == 'N' || a == 'O')return '6';
    if (a == 'P' || a == 'R' || a == 'S')return '7';
    if (a == 'T' || a == 'U' || a == 'V')return '8';
    if (a == 'W' || a == 'X' || a == 'Y')return '9';
}
string a[20010];
string b[20010];
string c[20010];
bool cmp(string a, string b)
{
    if (a.size() != b.size())
        return a.size() > b.size();
    else
        return a < b;
}
map<string, vector<int>>mp;
int main(){
    int cnt1 = 0, cnt2 = 0;
    string s;
    while (cin >> s)
    {
        if (s == "#")
            break;
        if (s[0] <= '9' && s[0] >= '0')
        {
            s.erase(3, 1);
            b[cnt2++] = s;
        }
        else
            a[cnt1++] = s;
    }
    sort(a, a + cnt1, cmp);
    for (int i = 0; i < cnt1; i++)
    {
        int len = a[i].size();
        for (int j = 0; j < len; j++)
            c[i].push_back(r(a[i][j]));
        mp[c[i]].push_back(i);
    }
    for (int i = 0; i < cnt2; i++, cout << endl)
    {
        for (int w = 0; w < 3; w++)
            cout << b[i][w];
        cout << "-";
        for (int w = 3; w < 7; w++)
            cout << b[i][w];
        cout << ": ";
        int flag = 0;
        for (int j = 0; j < 7; j++)
        {
            if (flag)
                break;
            string now = b[i].substr(j);
            if (mp[now].size() != 0)
            {
                flag = 1;
                for (int k = 0; k < mp[now].size(); k++)
                {
                    for (int p = 0; p < j; p++)
                        cout << b[i][p];
                    if (j != 0)
                        cout << "-";
                    cout << a[mp[now][k]] << " ";
                }
            }
        }
        if (!flag)
        {
            cout << "No words";
        }
    }
    return 0;
}

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值