之前做过的oj, acm题目忘了很多了, 又要开始要刷题了, go on!
#1260 : String Problem I
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
我们有一个字符串集合S,其中有N个两两不同的字符串。
还有M个询问,每个询问给出一个字符串w,求有多少S中的字符串可以由w添加恰好一个字母得到。
字母可以添加在包括开头结尾在内的任意位置,比如在"abc"中添加"x",就可能得到"xabc", "axbc", "abxc", "abcx".这4种串。
输入
第一行两个数N和M,表示集合S中字符串的数量和询问的数量。
接下来N行,其中第i行给出S中第i个字符串。
接下来M行,其中第i行给出第i个询问串。
所有字符串只由小写字母构成。
数据范围:
N,M<=10000。
S中字符串长度和<=100000。
所有询问中字符串长度和<=100000。
输出
对每个询问输出一个数表示答案。
- 样例输入
-
3 3 tourist petr rng toosimple rg ptr
- 样例输出
-
0 1 1
二分查找,在大型数组中很常用。
#include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <string> #include <cmath> using namespace std; const int maxn = 10005; struct Node{ int len; string s; }nd[maxn]; int n,m; int Match(const string &s1, const string &s2){ bool isPlus = true; int j = 0; for(int i=0; i<s1.length(); i++){ if(s1[i] != s2[j]){ if(isPlus){ isPlus = false; }else{ return false; } }else{ j++; } } return true; } int cmp(const void* a, const void* b){ Node* aa = (Node *)a; Node* bb = (Node *)b; return aa->len - bb->len; } int main(){ freopen("in.txt", "r", stdin); int i,j, mid, left, right, target_len, test_start, cnt; string target; scanf("%d %d", &n, &m ); getchar(); for(int i=0; i<n; i++){ cin>>nd[i].s; nd[i].len = nd[i].s.length(); } qsort(nd, n, sizeof(nd[0]), cmp); for(i=0; i<m; i++){ cin>>target; target_len = target.length() + 1; left = 0; right = n-1; test_start = -1; while(left <= right){ mid = left + (right - left)/2; if(nd[mid].len == target_len){ j = mid-1; while(j>=0 && nd[j].len == nd[mid].len){ j--; } test_start = j + 1; break; }else if(nd[mid].len > target_len){ right = mid - 1; }else{ left = mid + 1; } } if(test_start == -1){ printf("%d ", 0); }else{ cnt = 0; for(j=test_start; nd[j].len == target_len; j++){ if(Match(nd[j].s, target)){ cnt++; } } printf("%d ", cnt); } } return 0; }