java—将单词串联起来,以获得一个单词,其中包含由单个字母组成的可能最长的子字符串

c9qzyr3d  于 2021-07-09  发布在  Java
关注(0)|答案(4)|浏览(211)

给出了n个单词的数组。每个单词都由小写字母组成(“a”-“z”)。我们的目标是以这样的方式连接单词,以便获得一个单词,其中包含由一个特定字母组成的尽可能长的子字符串。找出这样一个子串的长度。
示例:
给定n=3和words=['aabb','aaaa','bbab'],函数应该返回6。最好的连接方式之一是单词[1]+单词[0]+单词[2]='aaaaaa bbbbab'。最长的子字符串由字母“a”组成,其长度为6。
给定n=3和words=['xxbxx','xbx','x'],函数应该返回4。最好的连接方式之一是单词[0]+单词[2]+单词[1]='xxbxxbx'。最长的子字符串由字母“x”组成,其长度为4。
我知道我不应该张贴的答案,但可能会帮助某人谁是寻找一个最佳的解决方案。

class DailyCodingProblem4 {

    public static void main(String args[]) {
        String[] arr = { "aabb", "aaaa", "bbab" };
        int res = solution(arr);
        System.out.println(res);

        String[] arr2 = { "xxbxx", "xbx", "x" };
        res = solution(arr2);
        System.out.println(res);
    }

    private static int solution(String[] arr) {
        Map<Integer, Integer> prefix = new HashMap<>();
        Map<Integer, Integer> suffix = new HashMap<>();
        Map<Integer, Integer> both = new HashMap<>();
        for (int i = 0; i < arr.length; i++) {
            String word = arr[i];
            int j = 1;
            while (j < word.length() && word.charAt(0) == word.charAt(j)) {
                j++;
            }
            int key = word.charAt(0);
            if (j == word.length()) {
                if (both.containsKey(key)) {
                    Integer temp = both.get(key);
                    if (j > temp) {
                        both.put(key, j);
                    }
                } else {
                    both.put(key, j);
                }
            } else {
                if (suffix.containsKey(key)) {
                    Integer temp = suffix.get(key);
                    if (j > temp) {
                        suffix.put(key, j);
                    }
                } else {
                    suffix.put(key, j);
                }

                j = word.length() - 1;

                while (j > 0 && word.charAt(word.length() - 1) == word.charAt(j - 1)) {
                    j--;
                }

                key = word.charAt(word.length() - 1);
                if (prefix.containsKey(key)) {
                    Integer temp = prefix.get(key);
                    if (word.length() - j > temp) {
                        prefix.put(key, word.length() - j);
                    }
                } else {
                    prefix.put(key, word.length() - j);
                }
            }
        }
        int res = 0;
        for (Integer key : prefix.keySet()) {
            if (suffix.containsKey(key)) {
                int temp = prefix.get(key) + suffix.get(key);
                if (temp > res) {
                    res = temp;
                }
            }

        }

        for (Integer key : suffix.keySet()) {
            if (prefix.containsKey(key)) {
                int temp = prefix.get(key) + suffix.get(key);
                if (temp > res) {
                    res = temp;
                }
            }

        }

        for (Integer key : both.keySet()) {
            if (prefix.containsKey(key)) {
                int temp = prefix.get(key) + both.get(key);
                if (temp > res) {
                    res = temp;
                }
            }
            if (suffix.containsKey(key)) {
                int temp = both.get(key) + suffix.get(key);
                if (temp > res) {
                    res = temp;
                }
            }
        }

        return res;
    }
}
bwntbbo3

bwntbbo31#

一种可能的解决方案是生成所有可能的组合,并找出最长长度的子串,包含相同的字符;

import java.util.*;

class Test{
static int max = 0; // variable : holds largest length of substring
public static void main(String[] args) {
    String [] array = {"aabb", "aaaa", "bbab"};

    getLengthOfLongestSubString(array, 0, array.length-1);
    System.out.println(max);
}        

static void getLengthOfLongestSubString(String [] array, int l, int r){
    if(l==r){
        String s = "";
        for(int i=0; i<array.length; i++){
            s += array[i];
        } 
        int count = 1;
        String temp = "";
      //  System.out.println(s);
        for(int i = 1; i<s.length(); i++){
            if(s.charAt(i-1) == s.charAt(i)){
                temp += s.charAt(i-1);
                count++;
            }else{
                if(count > max){
                  //  System.out.println(temp);
                    max = count;
                }
                count = 1;
                temp = "";
            }
        }
    }else{
        for(int i=l; i<=r; i++){
            array = swap(array, l, i);
            getLengthOfLongestSubString(array, l+1, r);
            array = swap(array, l, i);
        }
    }
}

static String [] swap(String [] array, int i, int j){
    String temp = array[i];
    array[i] = array[j];
    array[j] = temp;

    return array;
  }
}
omqzjyyz

omqzjyyz2#

对于每封信,你需要知道:
完全由该字母组成的单词的总长度;
字母前缀最长和次长的单词;和
后缀最长和次长的单词
因为每个单词最多进入两个组,由它的开头和结尾字母决定,所以你可以在o(n)时间内搞清这一切。

db2dz4w8

db2dz4w83#


# include <iostream>

# include <vector>

# include <algorithm>

# include <string>

# include <map>

# include <utility>

# include <iterator>

using namespace std;

int parse_map(multimap<int,tuple<char,bool,int>>& record, char& c, multimap<int,tuple<char,bool,int>> :: iterator &mIt)
{ 
    int idx = -1;
    int retval = 0;
    bool notFound = false;

    if((get<bool>(mIt->second)) && mIt->first > 0)
    {
        retval +=mIt->first;
        if(mIt != record.begin())
            --mIt;
        else
            return retval;

        for(;mIt->first > 0; mIt-- )
        {
            if(get<char>(mIt->second) == c)
            {
                retval += mIt->first;
                break;
            }
            if(mIt == record.begin())
                break;
        }
        notFound = true;
    }
    else if(mIt->first > 0)
    {
        retval += mIt->first;
        idx = get<int>(mIt->second);
        for(;mIt->first > 0; mIt--)
        {
            if((get<bool>(mIt->second)) && (get<char>(mIt->second) == c))
            {
                retval += mIt->first;
                break;
            }
        }
        notFound = true;   
    }
    if(mIt->first > 0 || notFound) 
        mIt = record.begin();
    else 
    {
        retval -= mIt->first;
        auto mIte = record.end();
        --mIte;
        while((get<char>(mIte->second) != c) && (mIte->first > 0))
        {
            --mIte;
        }
        if(mIte->first > 0)
        {
            if(get<int>(mIte->second) != get<int>(mIt->second))
            {    
                retval = parse_map(record,c,mIte);
            }
            else
            {
                --mIte;
                if(mIte->first > 0)
                    retval = parse_map(record,c,mIte);
            }
        }
        return retval;
    }
    for(;mIt->first < 0; mIt++)
    {   
        //Prefix scenario
        if ((get<int>(mIt->second) != idx) && (get<char>(mIt->second) == c))
        {
            retval -= mIt->first;
            break;
        }
    }
    return retval;
}
int solution(vector<string> &A)
{
    int max_substring;
    max_substring = 0;
    int substring_idx = -1;
    multimap<int,tuple<char,bool,int>> record;
    for(int i = 0; i < A.size(); i++)
    {
        int count;
        count = 1;
        // 2 Corner cases, 1 empty and the other only has 1 char
        if(A[i].size() == 0)
            continue;
        else if(A[i].size() == 1)
        {
            tuple<char,bool,int> p = make_tuple(A[i].front(), true,i);
            multimap<int,tuple<char,bool,int>> :: iterator mIta;
            for(mIta = record.begin(); mIta != record.end(); mIta++)
            {
                if ((get<char>(mIta->second) == get<char>(p)) && get<bool>(mIta->second))
                    break;
            }
            if(mIta != record.end())
            {
                record.insert({count + mIta->first,p});
                record.erase(mIta);
            }
            else
            {
                record.insert({count,p});
            }
            continue;
        }

        for(int j = 1; j < A[i].size(); j++)
        {
            if (A[i][j] == A[i].front())
            {
                count ++;
            }
            else 
            {
                for(int g = A[i].size() -2; g > j; g--)
                {
                    char temp = A[i][g];
                    int len = 1;
                    while((temp == A[i][g-1]) && (g>j))
                    {    
                        len ++;
                        g--;
                    }       
                    max_substring = max(max_substring,len);
                }
                break;
            }
        }
        multimap<int,tuple<char,bool,int>> :: iterator mIta;
        if (A[i].size() == count)
        {
            tuple<char,bool,int> p = make_tuple(A[i].front(), true,i);

            for(mIta = record.begin(); mIta != record.end(); mIta++)
            {
                if ((get<char>(mIta->second) == get<char>(p)) && get<bool>(mIta->second))
                    break;
            }
            if(mIta != record.end())
            {
                record.insert({count + mIta->first,p});
                record.erase(mIta);
            }
            else
            {
                record.insert({count,p});
            }
            continue;
        }
        tuple<char,bool,int> p = make_tuple(A[i].front(), false,i);
        for(mIta = record.begin(); mIta != record.end(); mIta ++)
            if((mIta->first) == count)
                break;
        if(mIta != record.end())
        {    for(; mIta != record.upper_bound(count); mIta++)
            {
                if (get<char>(mIta->second) == get<char>(p))
                    record.erase(mIta);
                record.insert({count,p});
            }
        }
        else 
                record.insert({count,p});
        count = -1;
        for(int j = (A[i].size()-2); j >= 0; j--)
        {
            if(A[i][j] == A[i].back())
            { 
                count --;
            }
            else break;
        }
        p = make_tuple(A[i].back(), false,i);

        for(mIta = record.begin(); mIta != record.end(); mIta ++)
            if((mIta->first) == count)
                break;
        if(mIta != record.end())
        {    for(; mIta != record.upper_bound(count); mIta++)
            {
                if (get<char>(mIta->second) == get<char>(p))
                    record.erase(mIta);
                record.insert({count,p});
            }
        }
        else 
            record.insert({count,p});
    }
    //Tidying up spaghetti code #new implementation in helper for tidyness.
    int retval;
    retval = 0;

    auto mItb = record.begin();
    if(record.size() == 1)
        return mItb->first;

    auto mIte = record.end();
    --mIte;
    int idx = mItb->first;
    //  Chk postfix
    if(idx < 0)
    {
        while(mItb->first == idx)
        {
            char c = get<char>(mItb->second);
            retval = max(parse_map(record, c, mItb),retval);
            ++mItb;
        }
    }
    // Chk prefix
    mIte = record.end();
    mIte--;
    idx =  mIte->first;
    while(mIte->first == idx)
    {
        char c = get<char>(mIte->second);
        retval = max(parse_map(record, c, mIte),retval);
        --mIte;
    }
    return max(retval,max_substring);
}

int main()
{
    vector<string> A{"aabb", "aaaa", "bbab"};
    vector<string> B{"xxbxx", "xbx", "x"};
    vector<string> C{"dd", "bb", "cc", "dd"};
    vector<string> D{"abbba"};
    vector<string> E{"bb", "b", "aaa", "ab", "bba"};
    vector<string> F{"aaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaa"};
    cout<<"Expected_6 \t"<<"got \t"<<solution(A)<<endl;
    cout<<"Expected_4 \t"<<"got \t"<<solution(B)<<endl;
    cout<<"Expected_4 \t"<<"got \t"<<solution(C)<<endl;
    cout<<"Expected_3 \t"<<"got \t"<<solution(D)<<endl;
    cout<<"Expected_6 \t"<<"got \t"<<solution(E)<<endl;
    cout<<"Expected_24 \t"<<"got \t"<<solution(F)<<endl;

}

我用了带负键的多重Map。
后缀是负数,后缀是正数。
计数器用于跟踪位于中间的最长字符串,而无需在填充Map时串联。
多重Map将最大的数字自动排序为最负数和最正数
如果字符串仅由一个字符组成,则在将贴图填充为牌组上的小丑卡时,会将其串联起来。
Map的字段是[occurrence]
上面解释了出现的情况,char是所涉及的字母,bool是一个通配符小丑,不管怎样都会被添加。int以防止重新计算同一字符串(同一字符串上的后缀和前缀)。
2 while循环。1表示后缀偏移,1表示前缀偏移。返回最大值
在递归函数中,chk if bool,if so我们继续,直到找到下一个最大的前缀,它将最大化连接。
在递归函数中,如果初始情况不是bool,那么我们继续进行,直到找到小丑bool(见4)。看看为什么我们不需要走得更远)
添加对应的后缀(如果有的话)
这就是后缀偏差的重要性所在(7~9)是前缀偏差。这意味着我们可能会跳过最大的后缀。但是如果后缀足够大,那么后缀+任何小前缀和joker都有可能产生最长的字符串。因此,初始分支(见6.)比较最大偏差。

rt4zxlrg

rt4zxlrg4#

对于一个特定的字母,它最长的子字符串可以用以下两种方式之一形成
它可以形成一个单词的后缀+所有完全由该字母组成的单词+另一个单词的前缀。例如 'abxaa' + 'aaa' + 'a' + 'abvdf' 所以这里的子串长度 'a'7 . 要获得最长的子串,您需要
i) 获取该字符的最长后缀(不要包含只有该单词出现的单词,我们将在下一步使用它们)。例如在 ['aabb','aaaa','bbab'] 和字母 'a' 这将是 0 因为没有单词 'a' 是一个严格的前缀。
ii)获得只有该字母的所有单词的总长度。在这个例子中是这样的 4 (英寸 'aaaa' ).
iii)执行步骤i),但现在执行严格的前缀。举个例子 2 (英寸 'aabb' )
iv)将上述三个步骤的值相加。你得到了吗 0 + 4 + 2 = 6 例如字母 'a' .
子字符串可以完全位于单词内部。找出此类案例的最大长度。我们的例子是 1 在( 'bbab' ).
通过取这两个可能的解的最大值,你得到了该字母的最大长度子串。现在就为所有人表演这个 26 字母,取最大值。我会把它留给你执行,但让我知道如果你面临任何问题。时间复杂性是 O(Total length of all words) .

相关问题