সমস্ত-বাদে ম্যাচ সন্ধান করা


18

এই চ্যালেঞ্জটি নিম্নলিখিত সমস্যাটি সমাধান করার জন্য কোড লেখার বিষয়ে।

দুটি এবং দুটি স্ট্রিং দেওয়া আপনার কোডের নীচের বৈশিষ্ট্যগুলির সাথে A এর স্ট্রিংয়ের শুরু এবং শেষ সূচকগুলি আউটপুট করা উচিত।

  • এ এর স্ট্রিংয়ের সাথে স্ট্রিংয়ের একক অক্ষরের এক পর্যন্ত প্রতিস্থাপনের সাথে বি এর কিছু স্ট্রিংয়েরও মিল থাকা উচিত।
  • প্রথম সম্পত্তি সন্তুষ্ট করে এমন আর আর সাবস্ট্রিং থাকা উচিত নয়।

উদাহরণ স্বরূপ:

A = xxxappleyyyyyyy

B = zapllezzz

appleসূচকের সাথে সাবস্ট্রিং 4 8(1 থেকে সূচিককরণ) একটি বৈধ আউটপুট হবে।

স্কোর

আপনার উত্তরের স্কোরটি আপনার কোডের দৈর্ঘ্যের সমষ্টি হবে বাইটগুলিতে + আমার কম্পিউটারে যে সময় লাগে তার সেকেন্ডে যে সময়টি প্রতিটি এবং 2 মিলিয়ন দৈর্ঘ্যের স্ট্রিং এ এবং বি তে চালানো হয় computer

পরীক্ষা এবং ইনপুট

আমি আপনার কোডটি http://hgdownload.cse.ucsc.edu/goldenPath/hg38/chromosomes/ এ স্ট্রিং থেকে নেওয়া 1 মিলিয়ন দৈর্ঘ্যের দুটি স্ট্রিংয়ে চালাব

ইনপুটটি স্ট্যান্ডার্ডে থাকবে এবং কেবল দুটি লাইনে পৃথক পৃথক দুটি স্ট্রিং হবে।

ভাষা ও গ্রন্থাগার

আপনি যে কোনও ভাষা নিখরচায় উপলব্ধ সংকলক / দোভাষী / ইত্যাদি ব্যবহার করতে পারেন। লিনাক্স এবং কোনও লাইব্রেরির জন্য যা ওপেন সোর্স এবং লিনাক্সের জন্য অবাধে উপলব্ধ।

আমার মেশিনের সময়গুলি আমার মেশিনে চালিত হবে। এটি একটি এএমডি এফএক্স-8350 এইট-কোর প্রসেসরে একটি স্ট্যান্ডার্ড উবুন্টু ইনস্টল। এর অর্থ হল আপনার কোডটি চালাতে আমার সক্ষম হওয়া দরকার। ফলস্বরূপ, কেবল সহজেই উপলভ্য নিখরচায় সফ্টওয়্যার ব্যবহার করুন এবং দয়া করে আপনার কোডটি কীভাবে সংকলন করতে এবং চালাতে হয় তার সম্পূর্ণ নির্দেশাবলী অন্তর্ভুক্ত করুন।


আপনার আরও পরম স্কোরিং সংজ্ঞা দরকার need আপনার কম্পিউটারে সময় চালানো ভাল স্কোরিং পদ্ধতির মতো শোনায় না।
mbomb007

7
@ mbomb007 এটি কোডের গতি পরিমাপের একমাত্র বুদ্ধিমান উপায় এবং এটি সর্বদা পিপিসিজিতে দ্রুততম কোড প্রতিযোগিতায় ব্যবহৃত হয়! লোকেরা সাধারণত তাদের উত্তরে তাদের কম্পিউটারে তাদের স্কোর পোস্ট করে এবং ওপিটির জন্য অপেক্ষা করে তারপরে একটি নির্দিষ্ট স্কোর তৈরি করে। এটি অন্তত 100% দ্ব্যর্থহীন।

5
@ mbomb007 যা দ্রুততম কোডের জন্য খুব বহুল ব্যবহৃত স্কোরিং পদ্ধতি।
অপ্টিমাইজার

if(hash(str1 == test1 && str2 == test2)) print("100,150") else ..- চিন্তা?
জন ডিভোরাক

2
@ ফ্রাইআম দ্য এজিগম্যান একটি টাইয়ের খুব সম্ভবত সম্ভাব্য ইভেন্টে প্রথম উত্তরটি জিতে যায়। appleyমেলে দুটি বিকল্প প্রয়োজন apllez। হয়তো আপনি মিস করেছেন যে এটি apllবি তে আছে এবং নেই appl?

উত্তর:


4

সি ++ সময়: ও (এন ^ 2), অতিরিক্ত স্থান: ও (1)

আমার মেশিনের 15 কে ডেটা সম্পূর্ণ করতে 0.2s লাগবে।

এটি সংকলন করতে, ব্যবহার করুন:

g++ -std=c++11 -O3 code.cpp -o code

এটি চালাতে, ব্যবহার করুন:

./code < INPUT_FILE_THAT_CONTAINS_TWO_LINES_SPERATED_BY_A_LINE_BREAK

Explaination

ধারণা, সহজ স্ট্রিং এর জন্য s1এবং s2আমরা অফসেট চেষ্টা s2দ্বারা i:

s1: abcabcabc
s2: bcabcab

অফসেটটি যখন 3 হয়:

s1: abcabcabc
s2:    bcabcab

তারপরে, প্রতিটি অফসেটের জন্য i, আমরা s1[i:]এবং এর উপর একটি গতিশীল প্রোগ্রামিং স্ক্যান সম্পাদন করি s2। প্রত্যেকের জন্য jযাক f[j, 0]সর্বাধিক দৈর্ঘ্য হতে dযেমন যে s1[j - d:j] == s2[j - i - d: j - i]। একইভাবে, f[j, 1]সর্বোচ্চ দৈর্ঘ্য dযেমন স্ট্রিং s1[j - d:j]এবং সর্বোচ্চ s2[j - i - d:j - i]1 অক্ষর দ্বারা পৃথক করা যাক।

সুতরাং s1[j] == s2[j - i], আমাদের আছে:

f[j, 0] = f[j - 1, 0] + 1  // concat solution in f[j - 1, 0] and s1[j]
f[j, 1] = f[j - 1, 1] + 1  // concat solution in f[j - 1, 1] and s1[j]

অন্যথায়:

f[j, 0] = 0  // the only choice is empty string
f[j, 1] = f[j - 1, 0] + 1  // concat solution in f[j - 1, 0] and s1[j] (or s2[j - i])

এবং:

f[-1, 0] = f[-1, 1] = 0 

যেহেতু আমাদের কেবল চ [জ - ১,:] গণনা করতে চ [জ,,] প্রয়োজন, কেবলমাত্র ও (১) অতিরিক্ত স্থান ব্যবহৃত হয়।

শেষ অবধি, সর্বোচ্চ দৈর্ঘ্য হবে:

max(f[j, 1] for all valid j and all i)

কোড

#include <string>
#include <cassert>
#include <iostream>

using namespace std;

int main() {
    string s1, s2;
    getline(cin, s1);
    getline(cin, s2);
    int n1, n2;
    n1 = s1.size();
    n2 = s2.size();
    int max_len = 0;
    int max_end = -1;
    for(int i = 1 - n2; i < n1; i++) {
        int f0, f1;
        int max_len2 = 0;
        int max_end2 = -1;
        f0 = f1 = 0;
        for(int j = max(i, 0), j_end = min(n1, i + n2); j < j_end; j++) {
            if(s1[j] == s2[j - i]) {
                f0 += 1;
                f1 += 1;
            } else {
                f1 = f0 + 1;
                f0 = 0;
            }
            if(f1 > max_len2) {
                max_len2 = f1;
                max_end2 = j + 1;
            }
        }
        if(max_len2 > max_len) {
            max_len = max_len2;
            max_end = max_end2;
        }
    }
    assert(max_end != -1);
    // cout << max_len << endl;
    cout << max_end - max_len + 1 << " " << max_end << endl;
}

দুঃখিত, আমি কোডটি দেখছি এবং এটি খুঁজে পাচ্ছি না যে এটির জন্য একটি চরিত্র বাদে স্ট্রিংয়ের সম্ভাবনা কীভাবে বিবেচিত হয়, উদাহরণস্বরূপ "অ্যাপল" এবং "অ্যাপল"। আপনি ব্যাখ্যা করতে পারেন?
rorlork

@rcrmn ডায়নামিক প্রোগ্রামিং অংশটি এটিই করছে। বুঝতে, কিছু সাধারণ ক্ষেত্রে ম্যানুয়ালি f [j, 0] এবং f [j, 1] গণনা করার চেষ্টা করা সহায়ক। আগের কোডটিতে কিছু বাগ রয়েছে তাই আমি পোস্টটি আপডেট করেছি।
রায়

এই জন্য আপনাকে ধন্যবাদ. আপনি কি মনে করেন যে কোনও ও (এন লগ এন) সমাধানও হতে পারে?

2

সি ++

আমি এটি করার জন্য একটি ভাল অ্যালগরিদম ভাবার চেষ্টা করেছি, তবে আমি আজ কিছুটা বিভ্রান্ত হয়েছি এবং ভালভাবে কাজ করবে এমন কোনও কিছুই ভাবতে পারি না। এটি O (n ^ 3) সময়ে চলে, সুতরাং এটি খুব কম slow আমি যে অপশনটি ভেবেছিলাম তা তাত্ত্বিকভাবে দ্রুততর হতে পারত তবে ও (এন ^ 2) স্থান গ্রহণ করত এবং 1 এম ইনপুট সহ এটি আরও খারাপ হত।

এটি লজ্জাজনক, 15 কে এর ইনপুটগুলির জন্য 190 সেকেন্ড সময় নেয়। আমি এটির উন্নতি করার চেষ্টা করব। সম্পাদনা: মাল্টিপ্রসেসিং যুক্ত হয়েছে। 8 থ্রেডে 15 কে ইনপুট দেওয়ার জন্য এখন 37 সেকেন্ড সময় লাগে।

#include <string>
#include <vector>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic>
#undef cin
#undef cout
#include <iostream>

using namespace std;

typedef pair<int, int> range;

int main(int argc, char ** argv)
{
    string a = "xxxappleyyyyyyy";
    string b = "zapllezzz";

    getline(cin, a);
    getline(cin, b);

    range longestA;
    range longestB;

    using namespace std::chrono;

    high_resolution_clock::time_point t1 = high_resolution_clock::now();

    unsigned cores = thread::hardware_concurrency(); cores = cores > 0 ? cores : 1;

    cout << "Processing on " << cores << " cores." << endl;

    atomic<int> processedCount(0);

    vector<thread> threads;

    range* longestAs = new range[cores];
    range* longestBs = new range[cores];
    for (int t = 0; t < cores; ++t)
    {
        threads.push_back(thread([&processedCount, cores, t, &a, &b, &longestBs, &longestAs]()
        {
            int la = a.length();
            int l = la / cores + (t==cores-1? la % cores : 0);
            int lb = b.length();
            int aS = t*(la/cores);

            for (int i = aS; i < aS + l; ++i)
            {
                int count = processedCount.fetch_add(1);
                if ((count+1) * 100 / la > count * 100 / la)
                {
                    cout << (count+1) * 100 / la << "%" << endl;
                }
                for (int j = 0; j < lb; ++j)
                {
                    range currentB = make_pair(j, j);
                    bool letterChanged = false;
                    for (int k = 0; k + j < lb && k + i < la; ++k)
                    {
                        if (a[i + k] == b[j + k])
                        {
                            currentB = make_pair(j, j + k);
                        }
                        else if (!letterChanged)
                        {
                            letterChanged = true;
                            currentB = make_pair(j, j + k);
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (currentB.second - currentB.first > longestBs[t].second - longestBs[t].first)
                    {
                        longestBs[t] = currentB;
                        longestAs[t] = make_pair(i, i + currentB.second - currentB.first);
                    }
                }
            }
        }));
    }

    longestA = make_pair(0,0);
    for(int t = 0; t < cores; ++t)
    {
        threads[t].join();

        if (longestAs[t].second - longestAs[t].first > longestA.second - longestA.first)
        {
            longestA = longestAs[t];
            longestB = longestBs[t];
        }
    }

    high_resolution_clock::time_point t2 = high_resolution_clock::now();

    duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

    cout << "First substring at range (" << longestA.first << ", " << longestA.second << "):" << endl;
    cout << a.substr(longestA.first, longestA.second - longestA.first + 1) << endl;
    cout << "Second substring at range (" << longestB.first << ", " << longestB.second << "):" << endl;
    cout << b.substr(longestB.first, longestB.second - longestB.first + 1) << endl;
    cout << "It took me " << time_span.count() << " seconds for input lengths " << a.length() << " and " << b.length() <<"." << endl;

    char c;
    cin >> c;
    return 0;
}

আমি সত্যিই দুঃখিত যে এটি একটি খারাপ সমাধান। আরও ভাল সময়ে এটি সম্পাদন করার জন্য আমি একটি অ্যালগরিদম সন্ধান করছি, তবে আপাতত কিছুই খুঁজে পেলাম না ...
rorlork

ঠিক আছে, প্রয়োজনীয় কাজের জটিলতা O (n ^ 4) থেকে O (n ^ 5) এর কাছাকাছি হওয়া উচিত, তাই দীর্ঘ সময়ের জন্য একটি সময় দেওয়া হয়
হফমলে

আমি বিশ্বাস করি এটি সবচেয়ে খারাপ ক্ষেত্রে O (n ^ 3) এর মতো হওয়া উচিত, কমপক্ষে আমার অ্যালগরিদমের সাথে। যাইহোক, আমি নিশ্চিত একরকম বৃক্ষ অনুসন্ধানের মতো এটির উন্নতিতে কিছু করা যেতে পারে তবে আমি কীভাবে এটি বাস্তবায়িত হবে তা নিশ্চিত নই।
রোরলর্ক

ওহ হ্যাঁ, ও (এন ^ 3) এটির মনের মধ্যে অন্যরকম দৃষ্টিভঙ্গি ছিল যা ও (এন ^ 4) গ্রহণ করত, তবে এটি এখন এক্সডি দ্বারা
নিখরচায়

আপনি যদি দুটি বাহিরের লুপের i < a.length()জন্য i < a.length - (longestA.second - longestA.first)(জে এবং বেলথ (একই জন্য) সমান) থেকে চেক পরিবর্তন করেন তবে আপনি অল্প পরিমাণে সময় বাঁচাতে পারবেন যেহেতু আপনার বর্তমানতম দীর্ঘতমের চেয়ে ছোট কোনও ম্যাচ প্রক্রিয়া করার দরকার নেই
হফমেল

2

আর

মনে হয় আমি আগের সমাধানটির সাথে সমস্যাটিকে আরও জটিল করেছিলাম। এটি আগেরটির থেকে প্রায় 50% দ্রুত (15k স্ট্রিংয়ের 23 সেকেন্ড) এবং খুব সহজ।

rm(list=ls(all=TRUE))
a="xxxappleyyyyyyy"
b="zapllezzz"
s=proc.time()
matchLen=1
matchIndex=1
indexA = 1
repeat {    
    i = 0
    repeat {
        srch = substring(a,indexA,indexA+matchLen+i)
        if (agrepl(srch,b,max.distance=list(insertions=0,deletions=0,substitutions=1)))
            i = i + 1
        else {
            if (i > 0) {
                matchLen = matchLen + i - 1
                matchIndex = indexA
            }
            break
        }
    }
    indexA=indexA+1
    if (indexA + matchLen > nchar(a)) break
}
c(matchIndex, matchLen + matchIndex)
print (substring(a,matchIndex, matchLen + matchIndex))
print(proc.time()-s)

ভাষার কারণে এটি কোনও প্রতিযোগী হতে পারে না তবে এটি করতে আমি কিছুটা মজা করেছি।
এটির জটিলতা সম্পর্কে নিশ্চিত নন, তবে একক থ্রেড ব্যবহার করে বেশ কয়েকটি k 15k স্ট্রিংয়ের জন্য এটি 43 সেকেন্ড সময় নেয়। এর বৃহত্তম অংশটি ছিল অ্যারে বাছাই করা। আমি অন্য কয়েকটি গ্রন্থাগার চেষ্টা করেছি, তবে উল্লেখযোগ্য উন্নতি ছাড়াই।

a="xxxappleyyyyyyy"
b="zapllezzz"
s=proc.time()
N=nchar
S=substring
U=unlist
V=strsplit
A=N(a)
B=N(b)
a=S(a,1:A)
b=S(b,1:B)
a=sort(a,method="quick")
b=sort(b,method="quick")
print(proc.time()-s)
C=D=1
E=X=Y=I=0
repeat{
    if(N(a[C])>E && N(b[D])>E){
        for(i in E:min(N(a[C]),N(b[D]))){
            if (sum(U(V(S(a[C],1,i),''))==U(V(S(b[D],1,i),'')))>i-2){
                F=i
            } else break
        }
        if (F>E) {
            X=A-N(a[C])+1
            Y=X+F-1
            E=F
        }
        if (a[C]<b[D])
            C=C+1
            else
            D=D+1
    } else
        if(S(a[C],1,1)<S(b[D],1,1))C=C+1 else D=D+1
    if(C>A||D>B)break
}
c(X,Y)
print(proc.time()-s)

পদ্ধতি:

  • প্রতিটি স্ট্রিংয়ের জন্য একটি প্রত্যয় অ্যারে তৈরি করুন
  • প্রত্যয় অ্যারেগুলি অর্ডার করুন
  • প্রতিটি সূচনার সাথে তুলনা করে এক স্তম্ভিত ধরণের অ্যারেগুলির মধ্য দিয়ে প্রতিটি পদক্ষেপ করুন

অবশ্যই, আর এর সহজ সমাধান হ'ল বায়োকন্ডাক্টর ব্যবহার করা।
archaephyrryx

@archaephyrryx একটি বায়োকন্ডাক্টর সমাধান মজাদার হবে।

এটি হবে ... তবে দস্তাবেজগুলির আমার দ্রুত পড়ার বিষয়টি আমার মাথার উপরে। আমি যদি এই শব্দগুলি বুঝতে পারি :-)
মিকিটি

আমি আমার প্রথম মন্তব্য মুছলাম। আপনি অবশ্যই এই চ্যালেঞ্জের জন্য আপনার পছন্দ মতো যে কোনও ওপেন সোর্স লাইব্রেরি ব্যবহার করতে পারেন।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.