Substring umum terbesar


30

Buat program atau fungsi yang mengambil daftar string sebagai input, dan output string terpanjang yang merupakan substring dari semua string input. Jika ada beberapa substring dengan panjang yang sama, dan tidak lagi substring, output salah satu dari mereka.

  • Ini mungkin berarti mengeluarkan string kosong.
  • Jika ada beberapa output yang valid, Anda dapat output salah satu dari mereka. Anda tidak diharuskan untuk memberikan output yang konsisten untuk input yang diberikan selama output selalu valid.
  • Akan selalu ada setidaknya satu string dalam input, tetapi mungkin tidak ada string yang tidak kosong.
  • Semua karakter ASCII yang dapat dicetak dapat muncul di input. Anda dapat menganggap itu adalah satu-satunya karakter yang muncul.
  • Anda dapat mengambil input atau menghasilkan output dengan salah satu metode default .
  • Celah standar tidak diizinkan.
  • Ini adalah - semakin sedikit byte kode, semakin baik.

Kasus uji:

[Inputs] -> [Valid outputs (choose one)]

["hello", "'ello"] -> ["ello"]
["very", "much", "different"] -> [""]
["empty", "", "STRING"] -> [""]
["identical", "identical"] -> ["identical"]
["string", "stRIng"] -> ["st", "ng"]
["this one", "is a substring of this one"] -> ["this one"]
["just one"] -> ["just one"]
["", "", ""] -> [""]
["many outputs", "stuptuo ynam"] -> ["m", "a", "n", "y", " ", "o", "u", "t", "p", "s"]
["many inputs", "any inputs", "ny iii", "yanny"] -> ["ny"]
["%%not&", "ju&#st", "[&]alpha_numeric"] -> ["&"]


2
@ Adám Pertanyaan itu menanyakan sub urutan umum terpanjang , bukan substring.
Gagang pintu

1
Apakah string hanya alfanumerik, alfabet, atau hanya ascii yang dapat dicetak?
Perwujudan Ketidaktahuan

@EmbodimentofIgnorance Semua karakter ASCII yang dapat dicetak dapat muncul di input.
Sara J

2
@ Shaggy Umumnya, tidak. Jika keduanya dapat dibedakan, undefinedberarti tidak ada string output yang valid. Jika string kosong (atau string lain) adalah output yang valid, mengklaim tidak ada output yang valid salah.
Sara J

Jawaban:


8

Python 2 , 82 byte

f=lambda h,*t:h and max(h*all(h in s for s in t),f(h[1:],*t),f(h[:-1],*t),key=len)

Cobalah online!

Mengambil input splatted. Akan habis waktu untuk input di mana string pertama panjang

Idenya adalah untuk mengambil substring dari string pertama huntuk menemukan yang terpanjang yang muncul di semua string yang tersisa t. Untuk melakukannya, kami secara cabang melakukan penghapusan karakter pertama atau terakhir dari h.


Python 2 , 94 byte

lambda l:max(set.intersection(*map(g,l)),key=len)
g=lambda s:s and{s}|g(s[1:])|g(s[:-1])or{''}

Cobalah online!

Metode yang lebih langsung. Fungsi bantu gmenghasilkan set semua substring s, dan fungsi utama mengambil yang terpanjang di persimpangan mereka.


8

Brachylog (v2), 3 9 byte

{sᵛ}ᶠlᵒtw

Cobalah online!

Program lengkap. Input dari input standar (sebagai daftar string gaya JSON), output ke output standar.

Penjelasan

{sᵛ}ᶠlᵒtw
 s         Find a substring
  ᵛ          of every element {of the input}; the same one for each
{  }ᶠ      Convert generator to list
     lᵒt   Take list element with maximum length
        w  Output it

Tampaknya, urutan tiebreak stidak seperti pada hampir semua hal lain di Brachylog, jadi kita perlu menimpanya secara manual untuk menghasilkan output terpanjang. (Itu agak frustasi: empat karakter tambahan untuk penimpaan, ditambah dua karakter pengelompokan karena Brachylog tidak mem-parsing dua metapredicate berturut-turut.)

Brachylog's stidak mengembalikan substring kosong, jadi kita perlu sedikit trik untuk menyiasatinya: alih-alih membuat submission fungsi (yang biasanya dilakukan), kita menulis program lengkap, menghasilkan output standar. Dengan begitu, jika ada substring yang umum, kami hanya mengeluarkannya, dan kami selesai. Jika tidak ada substring umum, program keluar - tetapi masih tidak mencetak apa pun ke output standar, sehingga output string null seperti yang dimaksud.


1
Saya mencoba ini dengan input ["banyak inpuabts", "inabputs", "ny iabii", "yanabny"]. Saya harapkan hasilnya ab dan ny . Tetapi hanya mendapat hasil a . Apakah saya melakukan sesuatu yang salah?
t-clausen.dk

1
Ugh, sepertinya saya ingat urutan tiebreak untuk skesalahan, dan mengesampingkan urutan tiebreak agak mahal. Akan tetapi, lakukan itu sekarang, karena penting agar jawabannya benar. Entah bagaimana tidak ada kasus tes yang saya coba perhatikan perbedaannya.
ais523

1
@ ais523 Urutan smenghasilkan substring adalah dengan terlebih dahulu memberikan semua awalan input (terpanjang pertama), kemudian menjatuhkan yang pertama dan ulangi
Kroppeb

5

Jelly , 12 6 byte

Ẇ€f/ṫ0

Cobalah online!

Terima kasih kepada @JonathanAllan karena telah menghemat 6 byte!


Saya percaya Ẇ€œ&/Ṫḟ0akan melakukan pekerjaan dan menghemat empat byte karena sub-string sudah dipesan oleh panjang, maka hasil yang disaring akan menjadi; maka yang tersisa adalah ketika tidak ada kecocokan, tail menghasilkan angka nol, dan karena kita dijamin daftar karakter, kita dapat dengan mudah menyaringnya.
Jonathan Allan

juga saya pikir œ&/dapat diganti dengan f/menyimpan lain di sini
Jonathan Allan

Saya mengajukan permintaan tarik ke (mudah-mudahan) menjadikan hasil pengurangan daftar kosong menjadi daftar kosong (daripada menaikkan TypeError). Jika itu bergabung saya percaya bahwa jawaban ini kemudian bisa menjadi enam-byter dengan Ẇ€f/ṛ/.
Jonathan Allan

@ JonathanAllan terdengar bagus. Terima kasih atas tips lainnya - semoga Anda senang saya menggabungkannya.
Nick Kennedy

Ya, alasan saya untuk komentar itu adalah untuk memungkinkan Anda memasukkan ide-ide ke dalam posting Anda.
Jonathan Allan

5

Ruby 2.6, 76 59 54 byte

->a{*w=a;w.find{|r|w<<r.chop<<r[1..];a.all?{|s|s[r]}}}

Cobalah online! - Versi Ruby 2.5 (56 byte)

Bagaimana?

Buat daftar kecocokan potensial, awalnya diatur ke array asli. Iterasi pada daftar, dan jika sebuah string tidak cocok, tambahkan 2 string baru ke ujung daftar, memotong karakter pertama atau terakhir. Pada akhirnya kecocokan (akhirnya string kosong) akan ditemukan.

Terima kasih Kirill L untuk -2 byte dan histokrat untuk -2 lainnya


4

R , 119 116 108 106 byte

function(S,`?`=nchar,K=max(?S),s=Reduce(intersect,lapply(S,substring,0:K,rep(0:K,e=K+1))))s[which.max(?s)]

Cobalah online!

Temukan semua substring dari setiap string, temukan persimpangan setiap daftar substring, lalu akhirnya kembalikan (salah satu) yang terpanjang.

-3 byte terima kasih kepada Kirill L.

-8 byte menggunakan lapply sebagai gantinya Map

-2 byte terima kasih kepada Kirill L. lagi, menghapus kawat gigi


Saya tidak punya waktu untuk memeriksa, tetapi jika saya tidak salah, 2 kejadian ncharcukup untuk menyelamatkan sesuatu dengan menyatakan ncharsebagai operator yang tidak waspada.
Kirill L.

@ KirillL. ya, lebih pendek 2 byte. Terima kasih! Aliasing listjuga memberi kita -3 byte.
Giuseppe

Anda juga dapat menjatuhkan kawat gigi untuk -2
Kirill L.

@ KirillL. Terima kasih! Saya agak khawatir saya akan mulai melakukannya dengan kode produksi ...
Giuseppe

itulah masalah dengan bermain golf bahasa yang Anda gunakan setiap hari
MickyT

4

05AB1E , 14 9 8 byte

€Œ.«ÃéθJ

-6 byte terima kasih kepada @Adnan .

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

€Œ       # Get the substring of each string in the (implicit) input-list
       # Right-reduce this list of list of strings by:
    Ã    #  Only keep all the strings that are present in both list of strings
     é   # Sort by length
      θ  # And pop and push its last item
         # The substrings exclude empty items, so if after the reduce an empty list remains,
         # the last item will also be an empty list,
       J # which will become an empty string after a join
         # (after which the result is output implicitly)

1
Saya pikir €Œ.«Ãõªéθharus bekerja selama 9 byte.
Adnan

@ Adnan Tunggu, kami punya pengurangan .. Bagaimana saya melewatkan itu. : SI mencoba Å«Ã, tetapi tidak menyadari bahwa saya seharusnya menggunakannya .«Ã.. Terima kasih!
Kevin Cruijssen

1
Sebenarnya, saya pikir €Œ.«ÃéθJharus bekerja untuk 8.
Adnan

4

Zsh , 126 ... 96 byte

-3 byte dari aritmatika untuk, -6 byte dari implisit "$@"(terima kasih roblogic), -5 byte dari menghapus yang tidak dibutuhkan { }, -1 byte dari bentuk pendek for, -1 byte dengan menggunakan repeat, -1 byte dengan menggabungkan for s ($b)dengan tubuhnya, -13 byte dengan mengubah loop berulang keluar untuk beberapa jank eval.

for l
eval a=\( \$l\[{1..$#l},{1..$#l}\] \)&&b=(${${b-$a}:*a})
for s ($b)(($#x<$#s))&&x=$s
<<<$x

Cobalah online! Cobalah online! Cobalah online!

Kami membaca semua substring yang mungkin ke dalam array a, dan kemudian mengatur bke persimpangan array adan b. Konstruk ${b-$a}hanya akan menggantikan $apada iterasi pertama: Tidak seperti ekspansi saudara kandungnya ${b:-$a}, itu tidak akan menggantikan ketika bditetapkan tetapi kosong.

for l;                              # implicit "$@"

# === OLD ===
{
    a= i=                           # empty a and i
    repeat $[$#l**2]                # compound double loop using div/mod
        a+=($l[++i/$#l+1,i%$#l+1])  # append to a all possible substrings of the given line
#               1+i/$#l             # 1,1,1...,  1,1,2,2,2,... ...,  n,n
#                       1+i%$#l     # 1,2,3...,n-1,n,1,2,3,... ...,n-1,n
#       a+=( $l[       ,     ] )    # append that substring to the array
# === NEW ===
    eval a=\( \
        \$l\[{1..$#l},{1..$#l}\] \  # The {bracket..expansions} are not escaped
    \) &&
# ===     ===
    b=( ${${b-$a}:*a} )
#         ${b-$a}                   # if b is unset substitute $a
#       ${       :*a}               # take common elements of ${b-$a} and $a
#   b=(               )             # set b to those elements
}
for s ($b)                          # for every common substring
    (( $#x < $#s )) && x=$s         # if the current word is longer, use it
<<<$x                               # print to stdout

Bagaimana cara kerja bit ini? a+=( $l[1+i/$#l,1+i%$#l] )
roblogic

1
@roblogic Saya pikir saya sudah menjelaskannya dengan lebih baik sekarang, periksa hasil edit. Idenya adalah untuk mengulang ke n ^ 2 dan menggunakan / dan% alih-alih menggunakan 2 forloop bersarang
GammaFunction

1
Anda mungkin dapat memotongnya for l in "$@"hanya for l;- ini adalah trik bash
roblogic

Saya harus mengatakan, zsh jauh lebih elegan daripada bash. Tidak ada yang analog dengan perbandingan array bagus ini AFAIKb=(${${b-$a}:*a})}
roblogic

1
Ada beberapa hal rapi yang dapat Anda lakukan dengannya, dan itu tidak terlalu populer. Itu berarti saya menambahkan jawaban zsh untuk sebagian besar pertanyaan yang saya temui. : P Jika Anda ingin belajar zsh, saya sarankan man zshexpndan man zshparamterutama. Saya selalu membuatnya terbuka saat menulis jawaban.
GammaFunction

3

Haskell , 80 byte

import Data.List
f(x:r)=last$sortOn(0<$)[s|s<-inits=<<tails x,all(isInfixOf s)r]

Cobalah online!

Dapatkan semua sufiks ( tails) dari kata pertama xdalam daftar dan ambil semua awalan ( inits) dari sufiks tersebut untuk mendapatkan semua substring sdari x. Simpanlah masing s- masing isInfixOf allstring dalam daftar yang tersisa r. Mengurutkan mereka substring dengan panjang (menggunakan satu (0<$)trik ) dan kembali yang terakhir.


3

Retina 0.8.2 , 48 byte

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)
O#$^`
$.&
1G`

Cobalah online! Penjelasan:

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)

Untuk setiap akhiran string pertama, temukan awalan terpanjang yang juga merupakan substring dari semua string lainnya. Daftar semua awalan sufiks tersebut (yaitu substring). Jika tidak ada substring yang cocok, kami hanya berakhir dengan string kosong, yang memang kami inginkan.

O#$^`
$.&

Sortir substring dalam urutan panjang terbalik.

1G`

Simpan hanya yang pertama, yaitu substring terpanjang.


Biarkan nadalah sejumlah string argumen. Maka (?=(.*\n.*\1)*.*$)seharusnya begitu (?=(.*\n.*\1){n-1}.*$), bukan? Uji kasus:["very", "different", "much"] -> [""]
mazzy

1
@ Mazzy Saya tidak melihat masalah: Coba online!
Neil

Itu bukan masalah. dengan {n}Anda bisa menghapus pola awal dan akhir dan tetap (.+)(?=(.*\n.*\1){n}jika Retina memungkinkan untuk menulis nlebih pendek dari(?<=^.*).*$
mazzy

@ Mazzy Saya tidak bisa di Retina 0.8.2, dan di Retina 1 saya harus main-main dengan eval, yang mungkin akan lebih lama lagi.
Neil

3

Permintaan TSQL, 154 byte

USE master
DECLARE @ table(a varchar(999)collate Latin1_General_CS_AI,i int identity)
INSERT @ values('string'),('stRIng');

SELECT top 1x FROM(SELECT
distinct substring(a,f.number,g.number)x,i
FROM spt_values f,spt_values g,@ WHERE'L'=g.type)D
GROUP BY x ORDER BY-sum(i),-len(x)

Cobalah online

Buat case sensitif dengan mendeklarasikan kolom 'a' dengan collation yang berisi CS (case sensitif).

Memisahkan semua string dari 2540 posisi awal (banyak identik) tetapi nilai berguna berkisar antara 1 dan 2070 dan berakhir 0 hingga 22 karakter setelah posisi awal, posisi akhir bisa lebih lama dengan mengubah jenis ke 'P' daripada 'L', tetapi akan melumpuhkan kinerja.

String-string berbeda ini dalam setiap rownumber dihitung. Hitungan tertinggi akan selalu sama dengan jumlah baris dalam variabel tabel '@'. Membalik urutan pada jumlah yang sama akan membuat substring dengan sebagian besar pertandingan di atas hasil diikuti oleh panjang substring terbalik akan meninggalkan pertandingan terpanjang dengan sebagian besar pertandingan di atas. Kueri hanya memilih 1 baris teratas.

Untuk mendapatkan semua jawaban, ubah bagian pertama kueri menjadi

PILIH 1 teratas dengan ikatan x DARI


3

C # (Visual C # Interactive Compiler), 320 257 byte

l=>(string.Join(",",l.Select(s=>new int[s.Length*s.Length*2].Select((i,j)=>string.Concat(s.Skip(j/-~s.Length).Take(j%-~s.Length))))
.Aggregate((a,b)=>a.Intersect(b)).GroupBy(x=>x.Length).OrderBy(x =>x.Key).LastOrDefault()?.Select(y=>y)??new List<string>()));

Cobalah online!

Props untuk @Expired Data dan @dana


Anda bisa mengembalikan string dari suatu fungsi. Jadi dalam kompiler Interaktif mungkin terlihat seperti ini: 294 byte
Expired Data

1
Inilah solusinya turun beberapa byte 215 byte
Expired Data

@ExpiredData ah sempurna ini adalah contoh yang saya butuhkan :)
Innat3



3

Perl 6 , 62 60 byte

{~sort(-*.comb,keys [∩] .map(*.comb[^*X.. ^*]>>.join))[0]}

Cobalah online!

Saya sedikit kesal Perl 6 tidak bisa melakukan operasi pada daftar daftar, itulah sebabnya ada tambahan .combdan >>di sana.

Hal menjengkelkan lainnya adalah maxtidak bisa berfungsi untuk membandingkan item, artinya saya harus menggunakannya sort. Seperti yang ditunjukkan dalam komentar, max dapat mengambil argumen, namun berakhir lebih lama karena saya harus mempertimbangkan maxmengembalikan infinity negatif ketika ada substring umum ( Coba online! ).


3
maxdapat mengambil fungsi seperti itu (arity 1), baik dengan posisi ketika dipanggil dalam mode OO, atau :byargumen bernama dalam mode prosedural.
Ven

2

Japt v2.0a0 -hF, 8 byte

Îã f@eøX

Terima kasih kepada Shaggy karena telah menghemat 3 byte

Cobalah

Îã              //Generate all substrings of the first string
 f@             //Filter; keep the substrings that satisfy the following predicate:
   e            //    If all strings of the input...
    øX          //    Contain this substring, then keep it
-h              //Take last element
-F              //If last element is undefined, default to empty string

Anda tidak perlu menyortir menurut panjangnya, menghemat 3 byte. Juga, -Fdefault ke string kosong.
Shaggy

2

Japt -h , 8 byte

(Saya bisa menghilangkan 3 byte terakhir dan menggunakan -Fhflag, tapi saya bukan penggemar menggunakan -F)

mã rf iP

Cobalah atau jalankan semua test case

mã rf iP     :Implicit input of array
m            :Map
 ã           :  Substrings
   r         :Reduce by
    f        :  Filter, keeping only elements that appear in both arrays
      i      :Prepend
       P     :  An empty string
             :Implicit output of last element


1

Python 2 , 103 byte

lambda b:max(reduce(set.__and__,[{d[f:e]for e in range(len(d)+2)for f in range(e)}for d in b]),key=len)

Cobalah online!

Ini adalah lambda anonim yang mengubah setiap elemen menjadi himpunan semua substring, lalu reduces dengan mengatur persimpangan ( set.__and__) dan kemudian mengembalikan maxelemen dengan length.


1 byte lebih pendek dengan set.intersection.
Ovs


1

Perl 5 ( -aln0777F/\n/ -M5.01 -MList::util=max), 99 byte

mungkin golf lebih pasti

map/(.+)(?!.*\1)(?{$h{$&}++})(?!)/,@F;say for grep{y///c==max map y///c,@b}@b=grep@F==$h{$_},keys%h

TIO


1

JavaScript (ES6),  98  92 byte

a=>(g=b=s=>a.every(x=>~x.indexOf(s))?b=b[s.length]?b:s:g(s.slice(0,-1,g(s.slice(1)))))(a[0])

Cobalah online!


1

Arang , 30 byte

≔⊟θη≔⁰ζFLη«≔✂ηζ⊕ι¹ε¿⬤θ№κεPε≦⊕ζ

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Algoritma ini lebih efisien dan juga lebih pendek daripada menghasilkan semua substring. Penjelasan:

≔⊟θη

Pop string terakhir dari daftar input ke dalam variabel.

≔⁰ζ

Batalkan indeks mulai substring.

FLη«

Simpulkan semua kemungkinan indeks akhir substring. (Sebenarnya ini loop dari 0 tidak termasuk panjang, sehingga nilainya disesuaikan nanti.)

≔✂ηζ⊕ι¹ε

Dapatkan substring saat ini.

¿⬤θ№κε

Periksa apakah substring ini terkandung dalam semua string input lainnya.

Pε

Jika kemudian mencetak setiap substring output sebelumnya.

≦⊕ζ

Kalau tidak, coba tambahkan indeks mulai substring.


1

Bash , 295 .. 175 byte

Tidak cantik tapi setidaknya berhasil. Cobalah secara Online

-37 dengan pembersihan umum ; -52 dengan menjiplak jawaban zsh ; -26 dengan mengganti array dengan loop ; -2 Berkat GammaFunction ; -3 dihapus i=0dari forloop

for l;{ d=${#l}
for((;i<d**2;i++)){ a="${l:i/d:1+i%d}" k=
for n;{ [[ $n =~ $a ]]&&((k++));}
((k-$#))||b+=("$a");};}
for e in "${b[@]}";do((${#e}>${#f}))&&f="$e";done
echo "$f"

Inilah skrip asli yang tidak diubah dengan komentar


1
Simpan 2 lagi: Anda dapat menggantinya ((k==$#))&&dengan ((k-$#))||. Ini juga memungkinkan Anda menggunakan k=alih-alih mengaturnya ke 0.
GammaFunction

1
Saya pikir "Tidak cantik tapi setidaknya berhasil" adalah MO untuk skrip bash :)
joeytwiddle

0

Merah , 266 174 byte

func[b][l: length? s: b/1 n: 1 until[i: 1 loop n[t: copy/part at s i l r: on foreach u
next b[r: r and(none <> find/case u t)]if r[return t]i: i + 1]n: n + 1 1 > l: l - 1]""]

Cobalah online!

Mengubah rekursi menjadi iterasi dan menyingkirkan penyortiran.



0

JavaScript (Node.js) , 106 byte

a=>(F=(l,n,w=a[0].substr(n,l))=>l?n<0?F(--l,L-l):a.some(y=>y.indexOf(w)<0)?F(l,n-1):w:"")(L=a[0].length,0)

Cobalah online!

a=>(                      // Main function
 F=(                      //  Helper function to run through all substrings in a[0]
  l,                      //   Length
  n,                      //   Start position
  w=a[0].substr(n,l)      //   The substring
 )=>
 l?                       //   If l > 0:
  n<0?                    //    If n < 0:
   F(--l,L-l)             //     Check another length
  :a.some(                //    If n >= 0: 
   y=>y.indexOf(w)<0      //     Check whether there is any string not containing the substring
                          //     (indexOf used because of presence of regex special characters)
  )?                      //     If so:
   F(l,n-1)               //      Check another substring
  :w                      //     If not, return this substring and terminate
                          //     (This function checks from the longest substring possible, so
                          //      it is safe to return right here)
 :""                      //   If l <= 0: Return empty string (no common substring)
)(
 L=a[0].length,           //  Starts from length = the whole length of a[0]
 0                        //  And start position = 0
)

0

Gaia , 15 byte

eḋ¦&⊢⟨:l¦:⌉=¦⟩∇

Cobalah online!

e		| eval as code
 ḋ¦		| find all non-empty substrings
   &⊢		| Reduce by set intersection
              ∇	| and return the first element where
      ⟨:l¦:⌉=¦⟩	| the length is equal to the max length

0

PowerShell , 165 163 87 byte

-76 bytes terima kasih kepada Nail untuk regexp yang mengagumkan .

"$($args-join'
'|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)"-a -ca|% m*|sort Le*|select -l 1)"

Cobalah online!

Kurang bermain golf:

$multilineArgs = $args-join"`n"
$matches = $multilineArgs|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)" -AllMatches -CaseSensitive|% matches
$longestOrNull = $matches|sort Length|select -Last 1
"$longestOrNull"




0

Pyth , 16 byte

eolN.U@bZm{s./dQ

Cobalah online!

       m     Q    # Map Q (parsed input) over the following function (lambda d:
          ./d     # Partitions of d (all substrings)
         s        # Reduce on + (make one list)
        {         # deduplicate
    .U            # reduce the result on the following lambda, with starting value result[0]
      @bZ         # lambda b,Z: Intersection between b and Z
                  # Result so far: all common substrings in random order
 o                # sort the resulting sets by the following lambda function:
  lN              # lambda N: len(N)
e                 # last element of that list
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.