Google Code jam 2013 Round 1C A题

类型:字符串 难度:1.5

 

Problem

In English, there are 26 letters that are either vowels or consonants. In this problem, we consider a, e, i, o, and u to be vowels, and the other 21 letters to be consonants.

A tribe living in the Greatest Colorful Jungle has a tradition of naming their members using English letters. But it is not easy to come up with a good name for a new member because it reflects the member's social status within the tribe. It is believed that the less common the name he or she is given, the more socially privileged he or she is.

The leader of the tribe is a professional linguist. He notices that hard-to-pronounce names are uncommon, and the reason is that they have too many consecutive consonants. Therefore, he announces that the social status of a member in the tribe is determined by its  n-value , which is the number of substrings with at least n consecutive consonants in the name. For example, when  n  = 3 , the name "quartz" has the  n-value  of 4 because the substrings quartz, uartz, artz, and rtz have at least 3 consecutive consonants each. A greater  n-value  means a greater social status in the tribe. Two substrings are considered different if they begin or end at a different point (even if they consist of the same letters), for instance "tsetse" contains 11 substrings with two consecutive consonants, even though some of them (like "tsetse" and "tsetse") contain the same letters.

All members in the tribe must have their names and n given by the leader. Although the leader is a linguist and able to ensure that the given names are meaningful, he is not good at calculating the  n-values . Please help the leader determine the  n-value  of each name. Note that different names may have different values of n associated with them.

Input

The first line of the input gives the number of test cases, T. T test cases follow. The first line of each test case gives the name of a member as a string of length L, and an integern. Each name consists of one or more lower-case English letters.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the  n-value  of the member's name.

Limits

1 ≤ T ≤ 100.
0 < n  L.

Small dataset

1 ≤ L ≤ 100.

Large dataset

1 ≤ L ≤ 106.
The input file will be no larger than 6MB.

 

题意分析:给定字符串,长度L,给定n,求满足条件的子串数目,条件:子串中含有连续n个辅音字符。

首先,给定一个长度为n的辅音序列在字符串s中的开始位置si,结束位置ei,求s中[st,en]范围(st<=si,ei<=en)内的包含该辅音序列的子串数,可用下式:cal(st,en,si,ei) {return (en-ei+1)*(si-st+1)}

一开始算法复杂度为O(L*n),但是超时,后来降到O(n)过了大数据,思路为:

设当前遍历到s的i位置,如果s[i]为元音,用lastpos记录位置并略过;

如果是辅音,设记录的上一个匹配的长度为n的辅音序列的第二个位置为lasti

如果[i-n+1,i]均为辅音(通过lastpos实现O(1)时间内判断),则令begin=MIN(lasti,i-n+1),为计算子串范围的起始位置,为的是与上一个匹配重复计算,之后将cal(begin,len(s)-1,i-n+1,i)累加入结果即可。

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define MIN(x,y) (x)<(y)?(x):(y)
using namespace std;

const int N=1010010;
char s[N];
int n;
bool isvow[26]={1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0};

long long cal(long long st,long long en,long long si,long long ei)
{
	return (en-ei+1)*(si-st+1);
}

int main()
{
	freopen("A-large-practice.in","r",stdin);
	freopen("A-large-practice.out","w",stdout);
	
	int t;
	scanf("%d",&t);
	for(int cnt=1;cnt<=t;cnt++)
	{
		scanf("%s%d",s,&n);
		long long ans=0;
		
		int ls = strlen(s);
		int lasti=0;
		int lastpos = -1;
		
		for(int i=0;i<ls;i++)
		{
			bool flag=1;
			if(isvow[s[i]-'a']==1)
			{
				lastpos = i;
				continue;
			}
			if(i>=n-1 && (lastpos==-1 || i-lastpos>=n))
			{
				int begin = MIN(lasti,i-n+1);
				ans += cal(begin,ls-1,i-n+1,i);
				//printf("%d %d %d %d\n",begin,ls-1,i-n+1,i);
				lasti = i-n+2;
			}
		}
		printf("Case #%d: %lld\n",cnt,ans);
	} 
} 


 

 

你可能感兴趣的:(C++,Google,OJ,Codejam)