题目描述
已知一个字符串数组words,要求寻找其中两个没有重复字符的字符串,使得这两个字符串的长度乘积最大,输出这个最大的乘积。如:
words=[“abcd”,“wxyh”,“defgh”], 其中不包含重复字符的两个字符串是"abcd"和"wxyh",则输出16
words=[“a”,“aa”,“aaa”,“aaaa”], 找不到满足要求的两个字符串,则输出0。
解题思路
由于测试用例的问题,这道题直接暴力破解是没有问题的,在考虑到时间复杂性上,我才用了一种新的思路。
暴力破解最大的问题在于需要直接会重复比较字符串,如果想要去除冗余,我们就应该保留比较的信息。遍历字符串中的每一个字符,为每一个字符保留一个vector记录所有含有该字符的字符下标,那么同一个vector数组中的字符一定是有重复的,到最后就可以找到所没有重复的字符读组。
这种思路是用空间复杂性换取时间复杂性,需要为每一个字符保留一个映射,初始假设所有字符串之间都是没有重复的,随着重复字符的出现消去所有重复的串对。
实现代码
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
vector<string> v;
vector<int> l;
map<char,vector<int> > mapper;
int len;
void StringSplit(const string& s,vector<string>&v,const string c){
string::size_type pos1,pos2;
pos2=s.find(c);
pos1=0;
string tmp;
while(string::npos!=pos2){
tmp=s.substr(pos1,pos2-pos1);
v.push_back(tmp);
pos1=pos2+c.length();
pos2=s.find(c,pos1);
}
if(pos1<s.length()){
tmp=s.substr(pos1);
v.push_back(tmp);
}
}
int main(){
string line,current;
getline(cin,line);
line=line.substr(1,line.length()-2);
StringSplit(line,v,",");
len=v.size();
if(len<2){
cout<<0<<endl;
return 0;
}
int i;
for(i=0;i<len;i++){
current=v[i];
if(current[0]=='"'&¤t[current.length()-1]=='"'){
v[i]=current.substr(1,current.length()-2);
l.push_back(v[i].length());
}
}
vector<vector<int> >lens(len,vector<int>(len,1));
vector<int>::iterator it;
for(i=0;i<v.size();i++){
current=v[i];
for(int j=0;j<current.length();j++){
if(mapper.count(current[j])!=0){
for(it=mapper[current[j]].begin();it!=mapper[current[j]].end();++it){
lens[i][*it]=0;
lens[*it][i]=0;
}
}
mapper[current[j]].push_back(i);
}
}
int maxv=0,mx;
for(i=0;i<len;i++){
mx=0;
for(int j=0;j<len;j++){
if(j!=i&&lens[i][j])
if(l[j]>mx)
mx=l[j];
}
if(l[i]*mx>maxv)
maxv=l[i]*mx;
}
cout<<maxv<<endl;
return 0;
}