題面:
一般的文本編輯器都有查找單詞的功能,該功能可以快速定位特定單詞在文章中的位置,有的還能統計出特定單詞在文章中出現的次數。
現在,請你編程實現這一功能,具體要求是:給定一個單詞,請你輸出它在給定的文章中出現的次數和第一次出現的位置。注意:匹配單詞時,不區分大小寫,但要求完全匹配,即給定單詞必須與文章中的某一獨立單詞在不區分大小寫的情況下完全相同 (參見樣例 1) ,如果給定單詞僅是文章中某一單詞的一部分則不算匹配(參見樣例 2) 。
Input
第 1 行爲一個字符串,其中只含字母,表示給定單詞;
第 2 行爲一個字符串,其中只可能包含字母和空格,表示給定的文章。
Output
只有一行, 如果在文章中找到給定單詞則輸出兩個整數, 兩個整數之間用一個空格隔開,分別是單詞在文章中出現的次數和第一次出現的位置(即在文章中第一次出現時,單詞首字母在文章中的位置,位置從 0 開始) ;如果單詞在文章中沒有出現,則直接輸出一個整數-1。
Sample Input
樣例 #1: To to be or not to be is a question 樣例 #2: to Did the Ottoman Empire lose its power at that time
Sample Output
樣例 #1: 2 0 樣例 #2: -1
Hint
【輸入輸出樣例 1 說明】
輸出結果表示給定的單詞 To 在文章中出現兩次,第一次出現的位置爲 0。
【輸入輸出樣例 2 說明】
表示給定的單詞 to 在文章中沒有出現,輸出整數-1。
【數據範圍】
1 ≤單詞長度≤10。
1 ≤文章長度≤1,000,000。
題意:
中文題還講的這麼模糊也是醉了(我讀題好弱啊。。):
(1)、求的是單詞相等,而不是字符串中的一部分相等,是完全一模一樣;
(2)、起點都是從0開始的。
我這裏用KMP來做這道題,我們先對待查的字符串先處理next[]數組,然後查詢待查詢的字符串,遇到剛好滿足KMP的字符串我們要看他是否左右是空格或者是邊界,如果是字符,就說明它還不是一個完整的單詞。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=1e6+5;
string a, b;
int nex[maxN], lena, lenb, cnt;
bool within(int x)
{
if( (b[x+1]<='z' && b[x+1]>='a') && x+1<lenb) return false;
if( (b[x-lena]<='z' && b[x-lena]>='a') && x-lena>=0) return false;
return true;
}
void cal_next()
{
int k=-1;
nex[0]=-1;
for(int i=1; i<lena; i++)
{
while(k>-1 && a[k+1]!=a[i]) k=nex[k];
if(a[k+1] == a[i]) k++;
nex[i]=k;
}
}
int KMP()
{
int pos=-1;
int k=-1;
cal_next();
for(int i=0; i<lenb; i++)
{
while(k>-1 && a[k+1]!=b[i]) k=nex[k];
if(a[k+1] == b[i]) k++;
if(k==lena-1)
{
if(!within(i)) { k=nex[k]; continue; }
k=-1;
if(pos==-1) pos=i-lena+1;
cnt++;
}
}
return pos;
}
int main()
{
a.clear(); b.clear();
while(getline(cin, a))
{
getline(cin, b);
cnt=0;
lena=(int)a.size();
lenb=(int)b.size();
for(int i=0; i<lena; i++) { if(a[i]<='Z' && a[i]>='A') a[i]+=32; }
for(int i=0; i<lenb; i++) { if(b[i]<='Z' && b[i]>='A') b[i]+=32; }
int ans=KMP();
if(cnt) printf("%d ", cnt);
printf("%d\n", ans);
a.clear(); b.clear();
}
return 0;
}